@cosmicdrift/kumiko-samples 0.385.0 → 0.387.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/LICENSE +21 -57
  2. package/README.md +1 -1
  3. package/package.json +2 -2
  4. package/packages/bundled-features/package.json +2 -2
  5. package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
  6. package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +0 -2
  7. package/packages/bundled-features/src/audit/screens.ts +1 -1
  8. package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +10 -10
  9. package/packages/bundled-features/src/auth-email-password/feature.ts +6 -6
  10. package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +3 -3
  11. package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
  12. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +1 -1
  13. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +18 -18
  14. package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +12 -12
  15. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
  16. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +24 -26
  17. package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +1 -1
  18. package/packages/bundled-features/src/auth-email-password/handlers/self-registration-status.query.ts +1 -1
  19. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +34 -37
  20. package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +6 -7
  21. package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +1 -5
  22. package/packages/bundled-features/src/auth-email-password/index.ts +5 -5
  23. package/packages/bundled-features/src/auth-email-password/lockout-store.ts +1 -1
  24. package/packages/bundled-features/src/auth-email-password/seeding.ts +63 -66
  25. package/packages/bundled-features/src/auth-email-password/signup-token-store.ts +8 -8
  26. package/packages/bundled-features/src/auth-email-password/testing.ts +3 -3
  27. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +57 -57
  28. package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +14 -14
  29. package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +15 -16
  30. package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +11 -12
  31. package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +1 -1
  32. package/packages/bundled-features/src/auth-email-password/web/constants.ts +3 -3
  33. package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +14 -14
  34. package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +11 -11
  35. package/packages/bundled-features/src/auth-email-password/web/index.ts +5 -5
  36. package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +17 -17
  37. package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +3 -4
  38. package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +16 -17
  39. package/packages/bundled-features/src/auth-email-password/web/session.tsx +34 -34
  40. package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +3 -3
  41. package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +14 -14
  42. package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +26 -27
  43. package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +12 -13
  44. package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +17 -18
  45. package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +11 -12
  46. package/packages/bundled-features/src/auth-foundation/boot-checks.ts +4 -4
  47. package/packages/bundled-features/src/auth-foundation/resolve-anonymous-access.ts +4 -4
  48. package/packages/bundled-features/src/auth-foundation/types.ts +2 -2
  49. package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +3 -3
  50. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +4 -4
  51. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +2 -2
  52. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  53. package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +1 -1
  54. package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -5
  55. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
  56. package/packages/bundled-features/src/auth-mfa/token-secrets.ts +1 -1
  57. package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +2 -2
  58. package/packages/bundled-features/src/auth-mfa/web/i18n.ts +3 -3
  59. package/packages/bundled-features/src/auth-mfa/web/index.ts +4 -4
  60. package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +17 -16
  61. package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +6 -6
  62. package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
  63. package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
  64. package/packages/bundled-features/src/billing-foundation/events.ts +22 -21
  65. package/packages/bundled-features/src/billing-foundation/feature.ts +42 -43
  66. package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
  67. package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +18 -17
  68. package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +11 -12
  69. package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -4
  70. package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +20 -20
  71. package/packages/bundled-features/src/billing-foundation/projection.ts +38 -37
  72. package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -3
  73. package/packages/bundled-features/src/billing-foundation/tenant-destroy-hook.ts +7 -8
  74. package/packages/bundled-features/src/billing-foundation/types.ts +64 -65
  75. package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +4 -4
  76. package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +1 -1
  77. package/packages/bundled-features/src/cap-counter/aggregate-id.ts +8 -9
  78. package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
  79. package/packages/bundled-features/src/cap-counter/enforce-cap.ts +64 -67
  80. package/packages/bundled-features/src/cap-counter/entity.ts +29 -29
  81. package/packages/bundled-features/src/cap-counter/feature.ts +34 -35
  82. package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +31 -31
  83. package/packages/bundled-features/src/cap-counter/handlers/mark-soft-warned.write.ts +4 -5
  84. package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +1 -1
  85. package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +3 -5
  86. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -3
  87. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
  88. package/packages/bundled-features/src/channel-email/smtp-transport.ts +34 -31
  89. package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +3 -4
  90. package/packages/bundled-features/src/compliance-profiles/feature.ts +15 -16
  91. package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +3 -6
  92. package/packages/bundled-features/src/compliance-profiles/handlers/list-profiles.query.ts +5 -5
  93. package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +4 -4
  94. package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +13 -14
  95. package/packages/bundled-features/src/compliance-profiles/handlers/sub-processors.query.ts +9 -11
  96. package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +7 -7
  97. package/packages/bundled-features/src/compliance-profiles/schema/profile-selection.ts +18 -23
  98. package/packages/bundled-features/src/compliance-profiles/seeding.ts +14 -15
  99. package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +3 -3
  100. package/packages/bundled-features/src/compliance-profiles-ops/index.ts +2 -2
  101. package/packages/bundled-features/src/config/handlers/readiness.query.ts +7 -7
  102. package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +4 -5
  103. package/packages/bundled-features/src/config/handlers/set.write.ts +4 -4
  104. package/packages/bundled-features/src/config/resolver.ts +4 -4
  105. package/packages/bundled-features/src/config/table.ts +10 -10
  106. package/packages/bundled-features/src/config/write-helpers.ts +1 -1
  107. package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +13 -12
  108. package/packages/bundled-features/src/custom-fields/aggregate-id.ts +16 -17
  109. package/packages/bundled-features/src/custom-fields/entity.ts +49 -47
  110. package/packages/bundled-features/src/custom-fields/events.ts +7 -8
  111. package/packages/bundled-features/src/custom-fields/feature.ts +70 -72
  112. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +9 -8
  113. package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +28 -26
  114. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +6 -7
  115. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +12 -13
  116. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +25 -28
  117. package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +6 -6
  118. package/packages/bundled-features/src/custom-fields/lib/field-access.ts +2 -2
  119. package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +1 -1
  120. package/packages/bundled-features/src/custom-fields/lib/quota.ts +1 -1
  121. package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -12
  122. package/packages/bundled-features/src/custom-fields/run-retention.ts +3 -3
  123. package/packages/bundled-features/src/custom-fields/schemas.ts +14 -14
  124. package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +2 -5
  125. package/packages/bundled-features/src/custom-fields/web/constants.ts +2 -2
  126. package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +26 -26
  127. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +65 -67
  128. package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +3 -3
  129. package/packages/bundled-features/src/data-retention/_internal/parse-override.ts +2 -3
  130. package/packages/bundled-features/src/data-retention/feature.ts +11 -18
  131. package/packages/bundled-features/src/data-retention/handlers/policy-for.query.ts +6 -6
  132. package/packages/bundled-features/src/data-retention/keep-for.ts +17 -17
  133. package/packages/bundled-features/src/data-retention/override-schema.ts +13 -15
  134. package/packages/bundled-features/src/data-retention/presets.ts +18 -23
  135. package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
  136. package/packages/bundled-features/src/data-retention/resolve-tenant-preset.ts +17 -16
  137. package/packages/bundled-features/src/data-retention/resolver.ts +33 -32
  138. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +71 -58
  139. package/packages/bundled-features/src/data-retention/schema/tenant-retention-override.ts +13 -11
  140. package/packages/bundled-features/src/delivery/feature.ts +3 -3
  141. package/packages/bundled-features/src/delivery/handlers/log.query.ts +1 -1
  142. package/packages/bundled-features/src/delivery/tables.ts +9 -8
  143. package/packages/bundled-features/src/delivery/unsubscribe.ts +4 -4
  144. package/packages/bundled-features/src/delivery/upsert-preference.ts +3 -4
  145. package/packages/bundled-features/src/document-ingest-foundation/entity.ts +5 -5
  146. package/packages/bundled-features/src/document-ingest-foundation/events.ts +2 -2
  147. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +2 -2
  148. package/packages/bundled-features/src/document-ingest-foundation/pages.ts +1 -1
  149. package/packages/bundled-features/src/document-ingest-foundation/tenant-destroy-hook.ts +4 -4
  150. package/packages/bundled-features/src/feature-toggles/compose-tier-resolver.ts +1 -1
  151. package/packages/bundled-features/src/feature-toggles/feature.ts +1 -1
  152. package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
  153. package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +5 -5
  154. package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
  155. package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
  156. package/packages/bundled-features/src/feature-toggles/web/constants.ts +1 -1
  157. package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
  158. package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
  159. package/packages/bundled-features/src/file-derivatives/presets.ts +1 -1
  160. package/packages/bundled-features/src/file-foundation/feature.ts +6 -6
  161. package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
  162. package/packages/bundled-features/src/file-provider-s3/feature.ts +16 -16
  163. package/packages/bundled-features/src/file-provider-s3/lib/s3-provider.ts +6 -6
  164. package/packages/bundled-features/src/files/feature.ts +6 -6
  165. package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +5 -5
  166. package/packages/bundled-features/src/files-tenant-data/hooks.ts +24 -26
  167. package/packages/bundled-features/src/files-tenant-data/index.ts +1 -1
  168. package/packages/bundled-features/src/folders/feature.ts +1 -1
  169. package/packages/bundled-features/src/folders/web/folder-manager.tsx +2 -2
  170. package/packages/bundled-features/src/folders/web/tree.ts +5 -5
  171. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
  172. package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
  173. package/packages/bundled-features/src/form-draft/entity.ts +3 -3
  174. package/packages/bundled-features/src/form-draft/feature.ts +4 -5
  175. package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
  176. package/packages/bundled-features/src/form-draft/release-file-refs.ts +6 -6
  177. package/packages/bundled-features/src/form-draft/schemas.ts +3 -3
  178. package/packages/bundled-features/src/form-draft/web/constants.ts +0 -2
  179. package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
  180. package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +4 -3
  181. package/packages/bundled-features/src/inbound-mail-foundation/constants.ts +30 -33
  182. package/packages/bundled-features/src/inbound-mail-foundation/entities.ts +47 -48
  183. package/packages/bundled-features/src/inbound-mail-foundation/events.ts +54 -50
  184. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +39 -39
  185. package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +8 -8
  186. package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +25 -26
  187. package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +7 -7
  188. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +50 -51
  189. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +8 -8
  190. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +10 -10
  191. package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +3 -4
  192. package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +11 -11
  193. package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +16 -15
  194. package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +31 -29
  195. package/packages/bundled-features/src/inbound-mail-foundation/provider-factory.ts +9 -9
  196. package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +45 -41
  197. package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
  198. package/packages/bundled-features/src/inbound-mail-foundation/types.ts +66 -67
  199. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +69 -68
  200. package/packages/bundled-features/src/inbound-provider-imap/credential-document.ts +13 -13
  201. package/packages/bundled-features/src/inbound-provider-imap/feature.ts +42 -40
  202. package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +20 -19
  203. package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +21 -21
  204. package/packages/bundled-features/src/jobs/db/queries/retention.ts +2 -2
  205. package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +3 -3
  206. package/packages/bundled-features/src/jobs/events.ts +1 -1
  207. package/packages/bundled-features/src/jobs/feature.ts +6 -7
  208. package/packages/bundled-features/src/jobs/handlers/detail.query.ts +4 -4
  209. package/packages/bundled-features/src/jobs/handlers/list.query.ts +1 -1
  210. package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
  211. package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +1 -1
  212. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  213. package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
  214. package/packages/bundled-features/src/jobs/job-run-logger.ts +14 -15
  215. package/packages/bundled-features/src/jobs/job-run-table.ts +3 -3
  216. package/packages/bundled-features/src/jobs/screens.ts +1 -1
  217. package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
  218. package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
  219. package/packages/bundled-features/src/ledger/entity.ts +5 -5
  220. package/packages/bundled-features/src/ledger/feature.ts +3 -3
  221. package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +3 -3
  222. package/packages/bundled-features/src/ledger/recurring.ts +12 -12
  223. package/packages/bundled-features/src/ledger/schemas.ts +1 -1
  224. package/packages/bundled-features/src/ledger/web/constants.ts +2 -2
  225. package/packages/bundled-features/src/ledger/web/index.ts +7 -7
  226. package/packages/bundled-features/src/legal-pages/feature.ts +40 -41
  227. package/packages/bundled-features/src/legal-pages/markdown.ts +3 -3
  228. package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +23 -24
  229. package/packages/bundled-features/src/legal-pages/web/index.ts +0 -2
  230. package/packages/bundled-features/src/mail-foundation/feature.ts +26 -27
  231. package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +27 -28
  232. package/packages/bundled-features/src/mail-transport-smtp/feature.ts +20 -20
  233. package/packages/bundled-features/src/managed-pages/branding.ts +6 -6
  234. package/packages/bundled-features/src/managed-pages/feature.ts +62 -62
  235. package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +5 -6
  236. package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +8 -8
  237. package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +5 -7
  238. package/packages/bundled-features/src/managed-pages/screens/page-screens.ts +11 -11
  239. package/packages/bundled-features/src/managed-pages/seeding.ts +8 -8
  240. package/packages/bundled-features/src/managed-pages/table.ts +16 -15
  241. package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +6 -6
  242. package/packages/bundled-features/src/managed-pages/web/i18n.ts +1 -1
  243. package/packages/bundled-features/src/notes-history/entity.ts +4 -4
  244. package/packages/bundled-features/src/notes-history/feature.ts +2 -2
  245. package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
  246. package/packages/bundled-features/src/page-render/layout.ts +9 -9
  247. package/packages/bundled-features/src/page-render/markdown.ts +11 -11
  248. package/packages/bundled-features/src/page-render/security-headers.ts +7 -6
  249. package/packages/bundled-features/src/personal-access-tokens/feature.ts +5 -5
  250. package/packages/bundled-features/src/personal-access-tokens/roles.ts +2 -2
  251. package/packages/bundled-features/src/readiness/handlers/status.query.ts +3 -3
  252. package/packages/bundled-features/src/renderer-foundation/api.ts +12 -13
  253. package/packages/bundled-features/src/renderer-foundation/constants.ts +2 -2
  254. package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
  255. package/packages/bundled-features/src/renderer-foundation/types.ts +11 -12
  256. package/packages/bundled-features/src/secrets/feature.ts +9 -9
  257. package/packages/bundled-features/src/secrets/web/constants.ts +2 -2
  258. package/packages/bundled-features/src/seo/feature.ts +3 -3
  259. package/packages/bundled-features/src/sessions/constants.ts +1 -1
  260. package/packages/bundled-features/src/sessions/feature.ts +9 -9
  261. package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +2 -2
  262. package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +2 -2
  263. package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
  264. package/packages/bundled-features/src/sessions/schema/user-session.ts +4 -4
  265. package/packages/bundled-features/src/sessions/screens.ts +2 -2
  266. package/packages/bundled-features/src/sessions/session-callbacks.ts +2 -2
  267. package/packages/bundled-features/src/sessions/session-revoked-event.ts +2 -2
  268. package/packages/bundled-features/src/shared/assert-no-where-rule-in-ownership-write.ts +1 -1
  269. package/packages/bundled-features/src/shared/decrypt-stored-pii.ts +1 -1
  270. package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
  271. package/packages/bundled-features/src/shared/map-with-concurrency.ts +5 -4
  272. package/packages/bundled-features/src/shared/parent-visibility.ts +2 -2
  273. package/packages/bundled-features/src/shared/password-hashing.ts +1 -1
  274. package/packages/bundled-features/src/shared/signup-handover.ts +1 -2
  275. package/packages/bundled-features/src/shared/single-use-token-store.ts +1 -1
  276. package/packages/bundled-features/src/subscription-mollie/constants.ts +15 -17
  277. package/packages/bundled-features/src/subscription-mollie/feature.ts +41 -42
  278. package/packages/bundled-features/src/subscription-mollie/index.ts +3 -3
  279. package/packages/bundled-features/src/subscription-mollie/plugin-methods.ts +17 -16
  280. package/packages/bundled-features/src/subscription-mollie/verify-webhook.ts +34 -34
  281. package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
  282. package/packages/bundled-features/src/subscription-stripe/feature.ts +44 -43
  283. package/packages/bundled-features/src/subscription-stripe/index.ts +6 -6
  284. package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +22 -27
  285. package/packages/bundled-features/src/subscription-stripe/runtime.ts +2 -2
  286. package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +62 -64
  287. package/packages/bundled-features/src/tags/feature.ts +3 -3
  288. package/packages/bundled-features/src/tags/screens.ts +1 -1
  289. package/packages/bundled-features/src/template-resolver/api.ts +10 -10
  290. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +5 -5
  291. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +1 -1
  292. package/packages/bundled-features/src/template-resolver/handlers/shared.ts +2 -2
  293. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +3 -3
  294. package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +3 -4
  295. package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +4 -5
  296. package/packages/bundled-features/src/template-resolver/seeding.ts +4 -4
  297. package/packages/bundled-features/src/template-resolver/table.ts +13 -14
  298. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
  299. package/packages/bundled-features/src/tenant/feature.ts +7 -7
  300. package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
  301. package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
  302. package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
  303. package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
  304. package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
  305. package/packages/bundled-features/src/tenant/invitation-table.ts +37 -40
  306. package/packages/bundled-features/src/tenant/membership-table.ts +3 -3
  307. package/packages/bundled-features/src/tenant/schema/tenant.ts +7 -9
  308. package/packages/bundled-features/src/tenant/screens.ts +1 -1
  309. package/packages/bundled-features/src/tenant/seeding.ts +19 -18
  310. package/packages/bundled-features/src/tenant/testing.ts +5 -6
  311. package/packages/bundled-features/src/tenant/web/constants.ts +2 -2
  312. package/packages/bundled-features/src/tenant-handover/events.ts +5 -7
  313. package/packages/bundled-features/src/tenant-handover/feature.ts +1 -1
  314. package/packages/bundled-features/src/tenant-handover/grant.ts +1 -1
  315. package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
  316. package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +8 -9
  317. package/packages/bundled-features/src/tenant-handover/signup-handover-provider.ts +1 -2
  318. package/packages/bundled-features/src/tenant-handover/transfer-graph.ts +4 -5
  319. package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
  320. package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
  321. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +2 -2
  322. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +1 -1
  323. package/packages/bundled-features/src/tenant-settings/constants.ts +1 -1
  324. package/packages/bundled-features/src/tenant-settings/tenant-defaults.ts +12 -5
  325. package/packages/bundled-features/src/tier-engine/aggregate-id.ts +15 -16
  326. package/packages/bundled-features/src/tier-engine/compose-app.ts +14 -14
  327. package/packages/bundled-features/src/tier-engine/entity.ts +18 -19
  328. package/packages/bundled-features/src/tier-engine/feature.ts +88 -87
  329. package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +6 -7
  330. package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +4 -4
  331. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +8 -8
  332. package/packages/bundled-features/src/tier-engine/tier-resolver.ts +2 -2
  333. package/packages/bundled-features/src/tier-engine/trial.ts +13 -13
  334. package/packages/bundled-features/src/tier-engine/web/index.ts +4 -4
  335. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +8 -8
  336. package/packages/bundled-features/src/user/handlers/create.write.ts +4 -4
  337. package/packages/bundled-features/src/user/schema/user.ts +45 -44
  338. package/packages/bundled-features/src/user/seeding.ts +40 -40
  339. package/packages/bundled-features/src/user/testing.ts +3 -3
  340. package/packages/bundled-features/src/user-data-rights/audit-download.ts +27 -28
  341. package/packages/bundled-features/src/user-data-rights/boot-checks.ts +1 -1
  342. package/packages/bundled-features/src/user-data-rights/deletion-token.ts +1 -1
  343. package/packages/bundled-features/src/user-data-rights/feature.ts +112 -113
  344. package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +9 -9
  345. package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +8 -8
  346. package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +29 -30
  347. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +40 -42
  348. package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +8 -9
  349. package/packages/bundled-features/src/user-data-rights/handlers/lift-restriction.write.ts +7 -8
  350. package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +2 -2
  351. package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +4 -4
  352. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion-by-email.write.ts +30 -29
  353. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +15 -18
  354. package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +42 -41
  355. package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +22 -19
  356. package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +8 -8
  357. package/packages/bundled-features/src/user-data-rights/index.ts +8 -10
  358. package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +3 -3
  359. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +24 -27
  360. package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +166 -276
  361. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +85 -107
  362. package/packages/bundled-features/src/user-data-rights/run-user-export.ts +67 -69
  363. package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +11 -11
  364. package/packages/bundled-features/src/user-data-rights/schema/download-token.ts +37 -41
  365. package/packages/bundled-features/src/user-data-rights/schema/export-job.ts +65 -67
  366. package/packages/bundled-features/src/user-data-rights/token-helpers.ts +21 -25
  367. package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +6 -6
  368. package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +6 -5
  369. package/packages/bundled-features/src/user-data-rights/web/constants.ts +1 -1
  370. package/packages/bundled-features/src/user-data-rights/web/index.ts +5 -5
  371. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +14 -13
  372. package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +13 -12
  373. package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +6 -6
  374. package/packages/bundled-features/src/user-data-rights/zip-path.ts +41 -40
  375. package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +15 -15
  376. package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +3 -5
  377. package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +45 -51
  378. package/packages/bundled-features/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +2 -2
  379. package/packages/bundled-features/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +1 -1
  380. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +3 -3
  381. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +32 -31
  382. package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +13 -13
  383. package/packages/bundled-features/src/user-profile/index.ts +3 -3
  384. package/packages/bundled-features/src/user-profile/web/client-plugin.ts +1 -1
  385. package/packages/bundled-features/src/user-profile/web/constants.ts +1 -1
  386. package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +1 -1
  387. package/packages/bundled-features/src/workflow-runner/aggregate-id.ts +1 -1
  388. package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -5
  389. package/packages/bundled-features/src/workflow-runner/event-trigger.ts +4 -15
  390. package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
  391. package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +4 -4
  392. package/packages/bundled-features/src/workflow-runner/pending-projection.ts +6 -7
  393. package/packages/bundled-features/src/workflow-runner/runner.ts +6 -6
  394. package/packages/bundled-features/src/workflow-runner/tables.ts +6 -6
  395. package/packages/bundled-features/src/workflow-runner/workflow-registry.ts +1 -1
@@ -1,26 +1,25 @@
1
- // Tenant-Invitations: Pre-Membership-Records mit Magic-Link-Token-Flow.
1
+ // Tenant invitations are pre-membership records using a magic-link token flow.
2
2
  //
3
3
  // Lifecycle:
4
- // 1. Admin invitet email → DB-Row entsteht mit status="pending",
5
- // Random-Token in Redis (signup-style bidirektional)
6
- // 2. Mail an die invited Email mit Activation-URL
7
- // 3. Klick auf Link → 3 Branches:
8
- // a) Eingeloggt + Email matched session-user → Membership-Add
9
- // b) Anonymous + Email existiert in users → Login → Auto-Accept
10
- // c) Anonymous + Email neu → Password setzen → user+membership entstehen
11
- // 4. Bei Erfolg: status="accepted", token aus Redis gelöscht (single-use-burn)
12
- // 5. Bei Cancel durch Admin: status="cancelled", token aus Redis gelöscht
13
- // 6. Bei TTL-Ablauf: Redis räumt Token, DB-Row bleibt mit status="pending"
14
- // (Cleanup-Job marked sie als "expired" — separater Concern)
4
+ // 1. An admin invites an email → a DB row is created with status="pending",
5
+ // and a random token is stored in Redis (signup-style bidirectional flow).
6
+ // 2. An email containing the activation URL is sent to the invitee.
7
+ // 3. Clicking the link follows one of three branches:
8
+ // a) Logged in + email matches the session user → membership is added
9
+ // b) Anonymous + email exists in users → login → automatic acceptance
10
+ // c) Anonymous + new email → set a password → user and membership are created
11
+ // 4. On success: status="accepted", and the Redis token is deleted (single-use).
12
+ // 5. When cancelled by an admin: status="cancelled", and the Redis token is deleted.
13
+ // 6. When the TTL expires: Redis removes the token, while the DB row remains
14
+ // status="pending" (a cleanup job marks it as "expired" separately).
15
15
  //
16
- // Single-Truth für expiry: Redis-TTL. DB-row.expiresAt ist nur UI-
17
- // Anzeige ("läuft in 6 Tagen ab"). Bei Lookup: pending in DB + token
18
- // nicht mehr in Redis → effectively expired, accept schlägt fehl mit
19
- // invalid-token.
16
+ // Redis-TTL is the single source of truth for expiry. DB-row.expiresAt is only
17
+ // for UI display ("expires in 6 days"). On lookup, a pending DB row without
18
+ // a Redis token is effectively expired, so acceptance fails with invalid-token.
20
19
  //
21
- // Idempotenz: zweiter invite für gleiche (tenantId, email) während
22
- // pending → re-use existing row + refresh Redis-token + send mail
23
- // (analog zu signup-Resend).
20
+ // Idempotency: a second invite for the same (tenantId, email) while pending
21
+ // reuses the existing row, refreshes the Redis token, and sends the email
22
+ // (analogous to signup resend).
24
23
 
25
24
  import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
26
25
  import {
@@ -34,9 +33,9 @@ import {
34
33
  // kumiko-lint-ignore cross-feature-import global-role options are owned by the user feature
35
34
  import { GLOBAL_ROLE_OPTIONS } from "../user/web/constants.ts";
36
35
 
37
- // Status-const-Object damit Handler-Code keine Magic-Strings nutzt.
38
- // Bei rename (z.B. "cancelled" → "revoked") fällt jeder caller auf
39
- // einmal auf statt verstreut über 5 Stellen.
36
+ // The status constant object prevents handler code from using magic strings.
37
+ // If a value is renamed (for example, "cancelled" → "revoked"), every caller
38
+ // fails at once instead of having stale values scattered across five locations.
40
39
  export const INVITATION_STATUS = {
41
40
  pending: "pending",
42
41
  accepted: "accepted",
@@ -45,11 +44,10 @@ export const INVITATION_STATUS = {
45
44
  } as const;
46
45
  export type InvitationStatus = (typeof INVITATION_STATUS)[keyof typeof INVITATION_STATUS];
47
46
 
48
- // Order MUSS bit-identisch zur DB-Migration sein. Object.values
49
- // bewahrt insertion-order (JS-spec-stable für string-keys). Wenn
50
- // jemand INVITATION_STATUS reordnet, generiert drizzle-kit eine
51
- // neue Migration. Hardcoded-Tuple zur Sicherheit gegen versehentliches
52
- // Refactoring der Object-Keys.
47
+ // The order MUST be bit-for-bit identical to the database migration. Object.values
48
+ // preserves insertion order (stable for string keys under the JS spec). Reordering
49
+ // INVITATION_STATUS generates a new drizzle-kit migration. The hardcoded tuple
50
+ // also guards against accidental refactoring of the object keys.
53
51
  export const INVITATION_STATUSES = [
54
52
  INVITATION_STATUS.pending,
55
53
  INVITATION_STATUS.accepted,
@@ -60,11 +58,11 @@ export const INVITATION_STATUSES = [
60
58
  export const tenantInvitationEntity = createEntity({
61
59
  table: "read_tenant_invitations",
62
60
  fields: {
63
- // Eingeladene Email — case-insensitive normalisiert beim Insert.
64
- // PII bis zur Annahme (danach hat der User selbst seine email in users).
61
+ // The invited email is normalized case-insensitively on insert.
62
+ // It remains PII until acceptance; afterward, the user owns the email in users.
65
63
  email: createTextField({ required: true, maxLength: 320, personal: "self", find: "exact" }),
66
- // Membership-Rolle die dem User nach Accept gegeben wird. Default
67
- // im handler ist "Admin" (Co-Admin-Pattern für kleine Teams).
64
+ // The membership role granted to the user on acceptance. The handler defaults
65
+ // to "Admin" (a co-admin pattern for small teams).
68
66
  role: createTextField({
69
67
  required: true,
70
68
  maxLength: 50,
@@ -85,11 +83,11 @@ export const tenantInvitationEntity = createEntity({
85
83
  required: true,
86
84
  default: "pending",
87
85
  }),
88
- // userId des einladenden Admins (für Audit-Trail "wer hat eingeladen").
86
+ // ID of the inviting admin, retained for the audit trail ("who invited").
89
87
  // Self-referencing ownerField: the field's own value IS the owner userId.
90
- // lookupable: the delete-hook filters "invitations sent by this user"
91
- // via the generated blind-index column instead of a full-tenant
92
- // decrypt-and-scan (see user-data-rights-defaults' invitation hook).
88
+ // lookupable: the delete hook filters "invitations sent by this user"
89
+ // through the generated blind-index column instead of decrypting and scanning
90
+ // the entire tenant (see user-data-rights-defaults' invitation hook).
93
91
  invitedBy: createTextField({
94
92
  required: true,
95
93
  personal: { of: "invitedBy" },
@@ -103,11 +101,10 @@ export const tenantInvitationEntity = createEntity({
103
101
  // UI-Anzeige — Wahrheit liegt in Redis-TTL.
104
102
  expiresAt: createTimestampField({ required: true }),
105
103
  },
106
- // Eine Invitation-Row pro (tenantId, email). Bei Re-Invite (Admin
107
- // invitet zweite Mal nach Cancel/Accept) wird die existing row
108
- // updated: status pending → cancelled → pending zurück, expiresAt
109
- // refreshed. Verhindert Token-Doppel-Gabe + macht Resend-Idempotenz
110
- // im handler trivial.
104
+ // One invitation row per (tenantId, email). On re-invite after cancellation or
105
+ // acceptance, the existing row is updated: status pending → cancelled → pending,
106
+ // and expiresAt is refreshed. This prevents duplicate tokens and makes resend
107
+ // idempotency trivial in the handler.
111
108
  indexes: [
112
109
  {
113
110
  unique: true,
@@ -12,9 +12,9 @@ import { createEntity, createTextField } from "@cosmicdrift/kumiko-framework/eng
12
12
  // the old serial-id design and keeps duplicate-write protection at the
13
13
  // database level independent of the handler lookup.
14
14
  //
15
- // Single-Source-of-Truth: `tenantMembershipEntity`. Die DB-Tabelle wird
16
- // aus der EntityDefinition über buildEntityTable abgeleitet, der
17
- // unique-Index ist via entity.indexes deklariert.
15
+ // Single source of truth: `tenantMembershipEntity`. The database table is
16
+ // derived from the EntityDefinition through buildEntityTable, and the
17
+ // unique index is declared via entity.indexes.
18
18
  export const tenantMembershipEntity = createEntity({
19
19
  table: "read_tenant_memberships",
20
20
  fields: {
@@ -21,9 +21,9 @@ export const tenantEntity = createEntity({
21
21
  description:
22
22
  "A tenant, the isolated workspace every other record belongs to, holding its key and display name, whether it is enabled, and its destruction-lifecycle state.",
23
23
  table: "read_tenants",
24
- // tenant.id IS the tenantId-value that every other table references as FK.
25
- // Alle tenantId-Spalten sind UUID (Migration 2026-04-16) → tenant.id muss
26
- // UUID sein, sonst findet der tenants-Lookup nie. Default gen_random_uuid().
24
+ // `tenant.id` is the `tenantId` value referenced by every other table as a foreign key.
25
+ // Every `tenantId` column is UUID, so `tenant.id` must also be UUID; otherwise
26
+ // the tenant lookup never finds a match. The default is `gen_random_uuid()`.
27
27
  fields: {
28
28
  key: createTextField({
29
29
  required: true,
@@ -59,12 +59,10 @@ export const tenantEntity = createEntity({
59
59
  destroyStartedAt: createTimestampField({}),
60
60
  destroyedAt: createTimestampField({}),
61
61
  },
62
- // tenant.key wird in Admin-URLs verwendet (`admin.<host>/<key>/...`) und
63
- // muss eindeutig sein. Ohne unique-constraint hätte ein konkurrenter
64
- // Self-Signup-Confirm einen TOCTOU-Race zwischen generateUniqueName-
65
- // isAvailable-check und insert: zwei Tabs könnten sequentiell denselben
66
- // Slug claimen, beide commits durch, der dritte User landet auf einem
67
- // shared admin-URL-prefix.
62
+ // `tenant.key` appears in admin URLs (`admin.<host>/<key>/...`) and must be unique.
63
+ // Without a unique constraint, concurrent self-signup confirmation could pass
64
+ // the `generateUniqueName` `isAvailable` check before either insert, allowing
65
+ // two tabs to claim the same slug and causing users to share an admin URL prefix.
68
66
  indexes: [{ unique: true, columns: ["key"] }],
69
67
  });
70
68
 
@@ -165,7 +165,7 @@ export function createMembersScreen(options?: {
165
165
  // feature.ts when `TenantFeatureOptions.inviteScreen` is set — see
166
166
  // createMembersScreen's doc comment above for why.
167
167
  export function createInviteCreateScreen(assignableAppRoles: AssignableAppRoles = new Map()) {
168
- // Admin sees this screen too, so only app roles Admin may grant are offered (fw#2414).
168
+ // Admin sees this screen too, so only app roles Admin may grant are offered.
169
169
  const appRoleOptions = [...assignableAppRoles]
170
170
  .filter(([, assignableFrom]) => isAssignableByRole(assignableFrom, "Admin"))
171
171
  .map(([role]) => role);
@@ -76,12 +76,13 @@ export type SeedTenantMembershipOptions = {
76
76
  };
77
77
 
78
78
  export type SeedTenantOptions = {
79
- /** Stable UUID — required for fixtures so the FE/BE können dieselbe ID
80
- * hardcoden (Sample-Switcher zeigt den Tenant beim Namen, der Test
81
- * prüft Memberships gegen exakt diese ID). Ohne ID müsste der Caller
82
- * den lookup-by-key extra machen. */
79
+ /**
80
+ * Stable UUID required for fixtures so the FE/BE can hardcode the same ID. The sample switcher
81
+ * displays the tenant by name, while tests verify memberships against this exact ID; without it,
82
+ * callers would need an extra lookup by key.
83
+ */
83
84
  readonly id: TenantId;
84
- /** URL-/Slug-Form (z.B. "dev", "acme"). Indexed unique in der DB. */
85
+ /** URL/slug form (for example, "dev" or "acme"). Indexed unique in the database. */
85
86
  readonly key: string;
86
87
  /** Human-readable label (im Switcher angezeigt). */
87
88
  readonly name: string;
@@ -89,7 +90,7 @@ export type SeedTenantOptions = {
89
90
  };
90
91
 
91
92
  // seedTenant runs through the raw event-store executor, which fires no
92
- // postSave hooks (#1463) — feature-registered entity hooks on "tenant"
93
+ // postSave hooks — feature-registered entity hooks on "tenant"
93
94
  // (e.g. tier-engine's auto-default-tier, an app's auto-default-compliance)
94
95
  // silently never run for tenants created this way. Pass `hooks` to fire
95
96
  // them explicitly, same lookup as the dispatcher (registry.getEntityPostSaveHooks
@@ -138,14 +139,14 @@ function buildSeedHookNotify(
138
139
  // registered entity/handler hooks fire (search-index/SSE system hooks are
139
140
  // wired at server-boot and out of reach here).
140
141
  //
141
- // Tenant re-scope (#1566): when `targetTenantId` is set we rebuild the
142
+ // Tenant re-scope: when `targetTenantId` is set we rebuild the
142
143
  // tenant-bound pieces of the context (`_tenantId`, `db`, `notify`,
143
144
  // `hasFeature`, `user.tenantId`) — a shallow `{ ...ctx, _tenantId }` left
144
145
  // closures over the caller's tenant (self-signup is anonymous/system).
145
146
  // `query`/`write` bridges still share the caller's identity; hooks that
146
147
  // need a full identity switch use `writeAs`/`queryAs`.
147
148
  //
148
- // afterCommit (#1566): when `hooks.context.scheduleAfterCommit` is present
149
+ // afterCommit: when `hooks.context.scheduleAfterCommit` is present
149
150
  // (HandlerContext from a live write), afterCommit hooks are queued onto the
150
151
  // dispatcher's sink and flush post-commit. Without a sink (fixture / plain
151
152
  // Connection) they still fire immediately — there is no outer TX to wait for.
@@ -255,20 +256,20 @@ export async function seedTenant(
255
256
  hooks?: SeedTenantHooks,
256
257
  ): Promise<{ id: TenantId }> {
257
258
  const by = options.by ?? TestUsers.systemAdmin;
258
- // executor.create erwartet eine TenantDb (mit .insert()-API), nicht
259
- // die rohe DbConnection. Auch wenn das Tenant-Aggregat selbst NICHT
260
- // tenant-scoped ist, braucht der Wrap-Layer für die runtime-API zu
261
- // existieren. by.tenantId reicht — keine Override-Semantik wie bei
262
- // seedTenantMembership nötig.
259
+ // executor.create expects a TenantDb with an .insert()-API, not the raw
260
+ // DbConnection. Although the tenant aggregate is not tenant-scoped, the
261
+ // wrapper is required by the runtime API. by.tenantId is sufficient; unlike
262
+ // seedTenantMembership, no override semantics are needed.
263
263
  const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
264
264
 
265
265
  const existing = await fetchOne(db, tenantTable, { id: options.id });
266
266
  if (existing) return { id: options.id };
267
267
 
268
- // Idempotenz: Aggregate kann im Event-Store existieren ohne Projection-Row
269
- // (Projection-Drift nach rebuild, manuellem DELETE, oder async-lag). Wenn
270
- // Stream-Version > 0 → kein create() — wäre version_conflict. Caller
271
- // bekommt die ID, Projection wird beim nächsten Dispatcher-Cycle aufgebaut.
268
+ // Idempotency: the aggregate may exist in the event store without a
269
+ // projection row (projection drift after a rebuild, manual DELETE, or async
270
+ // lag). If the stream version is > 0, skip create() to avoid
271
+ // version_conflict. Return the ID; the next dispatcher cycle can rebuild the
272
+ // projection.
272
273
  const streamVersion = await getUnscopedAggregateStreamMaxVersion(db, options.id);
273
274
  if (streamVersion > 0) return { id: options.id };
274
275
 
@@ -311,7 +312,7 @@ export async function seedTenantMembership(
311
312
  db: DbRunner,
312
313
  options: SeedTenantMembershipOptions,
313
314
  // Optional, append-only — same rationale as seedTenant's hooks param
314
- // (#1478): fires tenantMembership's postSave hooks (e.g. a Welcome-
315
+ // fires tenantMembership's postSave hooks (e.g. a Welcome-
315
316
  // notification or default-notification-preferences hook keyed off
316
317
  // `allOf: "tenantMembership"`) for fixtures/self-signup that opt in.
317
318
  // Omit to keep today's hook-less behavior.
@@ -1,8 +1,7 @@
1
- // /testing re-exportiert /seeding. Ehemalige Heimat der seed-Helpers,
2
- // jetzt nur noch Aggregation. Die Helpers leben in `/seeding` weil sie
3
- // genauso vom Dev-Server-Bootstrap (runDevApp) konsumiert werden — nicht
4
- // nur von Tests. Vertrag der Helpers ist stabil, test-spezifische
5
- // Knöpfe gehören NICHT hier rein (würde dev-boots brechen wenn jemand
6
- // einen lockout-test-Knopf einbaut).
1
+ // `/testing` re-exports `/seeding`; it is no longer the home of the seed helpers.
2
+ // The helpers live in `/seeding` because they are also consumed by the
3
+ // development-server bootstrap (`runDevApp`), not only by tests. Keep their
4
+ // stable contract here; test-specific options do not belong in this module,
5
+ // because they could break development boots when a lockout-test option is added.
7
6
 
8
7
  export * from "./seeding.ts";
@@ -21,11 +21,11 @@ export const MEMBER_ROLES_CELL_COMPONENT = "MemberRolesCell" as const;
21
21
 
22
22
  /** Closed allowlist for invite-role picker — never free text (escalation guard). */
23
23
  // Admin (rank 2) shares the invite-create screen with TenantAdmin — TenantAdmin
24
- // must not appear here or Admin sees an unassignable option (fw#2414).
24
+ // must not appear here or Admin sees an unassignable option.
25
25
  export const DEFAULT_INVITE_ROLE_OPTIONS = ["User", "Editor", "Admin"] as const;
26
26
  // Full rank list for memberRolesEditScreen: it is prefilled with a member's
27
27
  // *current* roles, so it must represent every rank a membership can hold,
28
- // including TenantAdmin (fw#2452). The screen hides what the caller may not
28
+ // including TenantAdmin. The screen hides what the caller may not
29
29
  // assign via TenantQueries.memberRoleAvailability.
30
30
  export const OWNER_INVITE_ROLE_OPTIONS = [
31
31
  "User",
@@ -1,12 +1,10 @@
1
1
  import * as z from "zod";
2
2
 
3
- // Audit trail for a completed claim (kumiko-framework#3035's audit-entry
4
- // requirement: names the source tenant, destination tenant, entities and
5
- // their counts). Its own aggregate, decoupled from the transferred root's
6
- // stream — same reasoning as
7
- // sessions' SESSION_REVOKED_EVENT: a fresh aggregate id per occurrence needs
8
- // no predecessor version and can never conflict with a concurrent write on
9
- // the entity it describes.
3
+ // Audit trail for a completed claim (audit-entry requirement: names the source tenant, destination
4
+ // tenant, entities and their counts). Its own aggregate, decoupled from the transferred root's
5
+ // stream — same reasoning as sessions' SESSION_REVOKED_EVENT: a fresh aggregate id per occurrence
6
+ // needs no predecessor version and can never conflict with a concurrent write on the entity it
7
+ // describes.
10
8
  //
11
9
  // _SHORT — r.defineEvent(short, schema) in feature.ts, framework prefixes it
12
10
  // to the QN below.
@@ -9,7 +9,7 @@ import { createSignupHandoverProvider } from "./signup-handover-provider.ts";
9
9
 
10
10
  export type TenantHandoverFeatureOptions = ClaimTenantHandoverOptions;
11
11
 
12
- // tenant-handover — Option A from kumiko-framework#3035: the ONE write a
12
+ // tenant-handover — the ONE write a
13
13
  // try-before-signup (or guest-checkout, demo-to-account) flow needs once an
14
14
  // anonymous run is done and the visitor has a fresh tenant. No general
15
15
  // tenant-merge tool, no copy — this is an ownership change on rows a
@@ -1,4 +1,4 @@
1
- // Try-before-signup ownership handover (kumiko-framework#3035), expressed as a
1
+ // Try-before-signup ownership handover, expressed as a
2
2
  // row-bound grant: the subject is the transferred run's own row id, the
3
3
  // anchor is the SOURCE tenant id it currently lives under. Redeeming the
4
4
  // grant is the ownership change itself — the claim handler's commitAnchor
@@ -31,7 +31,7 @@ function notTransferable(entityType: string): ReturnType<typeof writeFailure> {
31
31
  );
32
32
  }
33
33
 
34
- // The try-before-signup ownership handover (kumiko-framework#3035): claims an
34
+ // The try-before-signup ownership handover: claims an
35
35
  // anonymous run into the caller's own tenant, legitimized by a row-bound
36
36
  // grant the anonymous flow minted (see ../grant.ts). Idempotent — a second
37
37
  // call with the same token fails the same way a forged one would, because
@@ -1,4 +1,4 @@
1
- // The actual ownership change (kumiko-framework#3035): raw SQL against the
1
+ // The actual ownership change: raw SQL against the
2
2
  // read-model tables, because moving a row across the tenant boundary is
3
3
  // exactly the kind of write the framework's entity write map cannot express
4
4
  // (it is single-tenant-scoped by design — that boundary is the whole point
@@ -15,10 +15,10 @@
15
15
  // `transaction()` call, rolling back everything the handler already did).
16
16
  // `moveRootRow` — called as row-bound-grant's `commitAnchor` — is therefore
17
17
  // the ONLY statement that must itself combine the anchor-spend with the
18
- // first write (#3023's hard rule: a write issued after `ok: true` can lose
19
- // its work to a crash while the grant is already burned). Everything after
18
+ // first write: a write issued after `ok: true` can lose
19
+ // its work to a crash while the grant is already burned. Everything after
20
20
  // it rides the same transaction: if a later step throws (an undeclared
21
- // child entity, kumiko-framework#3035's named-error requirement), the WHOLE
21
+ // child entity, the named-error requirement), the WHOLE
22
22
  // transaction — root row included — rolls back, so a caller can safely
23
23
  // retry the same token after fixing the app's `transferable` declarations.
24
24
 
@@ -64,8 +64,7 @@ export async function moveRootRow(args: {
64
64
  // history + storage-usage counters — fileRef is a standard ES entity (see
65
65
  // files-storage-tracking.md), so without those two follow-ups a later write
66
66
  // against a moved fileRef can't load its stream, and a projection rebuild
67
- // would put the row back into the source tenant (kumiko-framework#3131-adjacent
68
- // gap, item 4).
67
+ // would put the row back into the source tenant.
69
68
  async function moveFileRefs(args: {
70
69
  readonly db: DbRunner;
71
70
  readonly registry: Registry;
@@ -210,7 +209,7 @@ async function moveEdgeRows(args: {
210
209
  // Everything the root ownership write does NOT cover: the root's own event
211
210
  // history + attached files, plus the rows, event history and attached files of
212
211
  // every descendant the declared transfer graph reaches, however deep and by
213
- // however many paths (#3088, #3131).
212
+ // however many paths.
214
213
  // Returns a count per moved entity name (the
215
214
  // write handler turns this into the audit entry) — `fileRef` is a single
216
215
  // pooled count across root + every child, since it is not itself part of the
@@ -264,7 +263,7 @@ export async function moveTransferGraph(args: {
264
263
 
265
264
  const adjacency = resolveTransferAdjacency(registry, rootEntityName);
266
265
 
267
- // A worklist, not a level-wise walk (#3131): each batch of rows that actually
266
+ // A worklist, not a level-wise walk: each batch of rows that actually
268
267
  // changed hands becomes the parent ids for the edges leading away from its
269
268
  // type. The same edge therefore runs again whenever a later round discovers
270
269
  // more rows of its parent type, which is what a type reachable by two paths
@@ -274,7 +273,7 @@ export async function moveTransferGraph(args: {
274
273
  // every statement filters on `tenantCol = sourceTenantId` and RETURNS only
275
274
  // the rows it flipped, so a row enters this worklist exactly once and the
276
275
  // source tenant holds finitely many. Do not add an edge-level visited set to
277
- // "bound" this — that is precisely the bug #3131 removed.
276
+ // "bound" this — that would reintroduce the bug.
278
277
  let pending: readonly { readonly entityName: string; readonly rowIds: readonly string[] }[] = [
279
278
  { entityName: rootEntityName, rowIds: [rootRowId] },
280
279
  ];
@@ -1,6 +1,5 @@
1
1
  // tenant-handover's implementation of the shared signup-handover extension
2
- // point (kumiko-framework#3035 follow-up, offlot-app#454): lets
3
- // auth-email-password's signup-request verify a grant against its root row
2
+ // point: lets auth-email-password's signup-request verify a grant against its root row
4
3
  // WITHOUT spending the anchor (the anchor is spent once, by the claim
5
4
  // signup-confirm runs afterwards, via a fresh short-lived grant this module
6
5
  // mints) — see shared/signup-handover.ts for the extension contract and
@@ -1,15 +1,14 @@
1
1
  // Resolves the declared transfer graph for a root entity type: the root
2
2
  // itself, plus every registered entity that reaches it through a declared
3
- // schema edge (kumiko-framework#3035, #3088; framework CLAUDE.md premise 4 —
4
- // the graph depth is read off the existing declarations, never a hand-
5
- // maintained per-app list).
3
+ // schema edge (framework CLAUDE.md premise 4 — the graph depth is read off
4
+ // the existing declarations, never a hand-maintained per-app list).
6
5
  //
7
6
  // The edge definition (parentRef + single-valued reference fields, minus
8
7
  // `handover: "stay"`) lives in the framework so the boot validator's depth
9
8
  // limit and the mover's traversal measure the same graph. What comes out is
10
9
  // static adjacency, not a walk: the mover drives the actual traversal from the
11
- // row ids it moves (#3131), because how deep a type sits depends on the rows
12
- // found, not on the schema alone.
10
+ // row ids it moves, because how deep a type sits depends on the rows found,
11
+ // not on the schema alone.
13
12
  //
14
13
  // `transferable: true` stays the only gate on what actually moves, and it is
15
14
  // enforced by the caller against edges that turn out to have rows rather than
@@ -16,7 +16,7 @@ const log = createFallbackLogger("kumiko:boot");
16
16
 
17
17
  // V4: tenantOwned-entity-without-hook gate. Mirrors user-data-rights' V3
18
18
  // (validateGdprPiiHookCoverage) but for EXT_TENANT_DATA. Registered as this
19
- // feature's own `r.bootCheck()` (#1314, moved off the framework-internal
19
+ // feature's own `r.bootCheck()` (moved off the framework-internal
20
20
  // boot-validator) — tenant-lifecycle owns EXT_TENANT_DATA
21
21
  // (r.extendsRegistrar), so its own mount is the trigger, matching the
22
22
  // original guard's "tenant-lifecycle mounted" gate exactly (unlike gating on
@@ -78,7 +78,7 @@ export function createTenantLifecycleFeature(): FeatureDefinition {
78
78
  r.extendsRegistrar(EXT_TENANT_LIFECYCLE_STATUS, {});
79
79
  r.useExtension(EXT_TENANT_LIFECYCLE_STATUS, "tenant-lifecycle", tenantLifecycleStatusPlugin);
80
80
 
81
- // GDPR-storage guard V4 (#1314) — moved off the framework-internal
81
+ // GDPR-storage guard V4 — moved off the framework-internal
82
82
  // boot-validator onto this feature's own r.bootCheck(), since it owns
83
83
  // EXT_TENANT_DATA: its own mount is the trigger, matching the original
84
84
  // guard's "tenant-lifecycle mounted" gate exactly.
@@ -427,7 +427,7 @@ export async function runTenantDestructionSweep(args: {
427
427
 
428
428
  let triggered = 0;
429
429
  for (const row of due) {
430
- const tenantId = row.id as TenantId;
430
+ const tenantId = row.id;
431
431
  const events = await loadAggregate(args.db, tenantId, tenantId);
432
432
  const version = lastEventVersion(events);
433
433
  const user = createSystemUser(tenantId);
@@ -469,7 +469,7 @@ export async function runTenantDestructionSweep(args: {
469
469
  deadlineAt: tenantDeadlineAt,
470
470
  db: args.db,
471
471
  registry: args.registry,
472
- tenantId: row.id as TenantId,
472
+ tenantId: row.id,
473
473
  log: args.log,
474
474
  fileProviderResolver: args.fileProviderResolver,
475
475
  searchAdapter: args.searchAdapter,
@@ -60,7 +60,7 @@ export type DestructionStageCtx = {
60
60
  // Derived search docs of the tenant record (its name) live in the writer's
61
61
  // index, not the destroyed tenant's, so the subject-keys stage purges them.
62
62
  readonly searchAdapter?: SearchAdapter;
63
- // fw#2914 — sourced from the owning job's ctx (_escapeHatchAuditSink,
63
+ // Sourced from the owning job's ctx (_escapeHatchAuditSink,
64
64
  // systemUser.id); runTenantDataHooks uses them to attribute+audit any
65
65
  // EXT_TENANT_DATA usage's declared escapeHatch.
66
66
  readonly escapeHatchAuditSink?: EscapeHatchAuditSink;
@@ -14,7 +14,7 @@ export const TENANT_SETTINGS_FEATURE_NAME = "tenant-settings";
14
14
  // strings (mirror tags' Handlers/Queries constants).
15
15
  export const TenantSettingsConfig = {
16
16
  // Shared with engine/constants.ts's TENANT_CURRENCY_CONFIG_KEY — a
17
- // `money` field's `currency: { kind: "tenant" }` declaration (fw#2933)
17
+ // `money` field's `currency: { kind: "tenant" }` declaration
18
18
  // resolves against this same key.
19
19
  currency: TENANT_CURRENCY_CONFIG_KEY,
20
20
  locale: "tenant-settings:config:locale",
@@ -15,6 +15,8 @@ import {
15
15
  type EntityDefinition,
16
16
  type WriteHandlerDef,
17
17
  } from "@cosmicdrift/kumiko-framework/engine";
18
+ import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
19
+ import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
18
20
  import * as z from "zod";
19
21
  import { TenantSettingsConfig } from "./constants.ts";
20
22
 
@@ -26,7 +28,7 @@ export function defineCreateWithTenantDefaults(
26
28
  options: {
27
29
  /** Required — this is a write-path helper; making it optional let a
28
30
  * forgetful caller register a create handler with no access rule at
29
- * all (fw#1581). */
31
+ * all. */
30
32
  readonly access: AccessRule;
31
33
  /** Money field names whose `currency` is filled from tenant-settings when missing. */
32
34
  readonly currencyFields?: readonly string[];
@@ -53,11 +55,16 @@ export function defineCreateWithTenantDefaults(
53
55
  schema,
54
56
  access: options.access,
55
57
  handler: async (event, ctx) => {
56
- const payload = { ...(event.payload as Record<string, unknown>) };
58
+ if (!isPlainObject(event.payload)) {
59
+ throw new InternalError({
60
+ message: `${entityName}:create payload must be an object after schema validation`,
61
+ });
62
+ }
63
+ const payload = { ...event.payload };
57
64
 
58
65
  for (const field of options.currencyFields ?? []) {
59
- const value = payload[field] as { amount?: number; currency?: string } | undefined;
60
- if (value && typeof value === "object" && !value.currency) {
66
+ const value = payload[field];
67
+ if (isPlainObject(value) && !value["currency"]) {
61
68
  const currency = await ctx.config?.(TenantSettingsConfig.currency);
62
69
  if (typeof currency === "string") payload[field] = { ...value, currency };
63
70
  }
@@ -68,7 +75,7 @@ export function defineCreateWithTenantDefaults(
68
75
  }
69
76
 
70
77
  // Re-validate against the unrelaxed entity schema so config-filled
71
- // values still honor select/enum field constraints (fw#1581) — and so
78
+ // values still honor select/enum field constraints — and so
72
79
  // a missing currency after failed/missing tenant-settings mount fails
73
80
  // loud instead of inserting half-filled money rows.
74
81
  const filled = baseSchema.parse(payload);
@@ -1,26 +1,25 @@
1
1
  import { v5 as uuidv5 } from "uuid";
2
2
 
3
- // Fixed UUID-namespace für die tier-assignment-aggregate-id-Ableitung.
4
- // Generiert einmalig (2026-05-02), in Stein gemeißelt: ein Wechsel würde
5
- // jeden existing aggregate-Stream re-keyen → kaputter event-replay,
6
- // kaputte projection-rebuilds, verlorener Tier-Wechsel-Audit. Der
7
- // drift-pin-Test in feature.test.ts pinnt diese Konstante.
3
+ // Fixed UUID namespace for deriving tier-assignment aggregate IDs.
4
+ // Generated once and immutable: changing it would re-key every existing
5
+ // aggregate stream, breaking event replay and projection rebuilds and losing
6
+ // the tier-change audit. The drift-pin test in feature.test.ts pins this constant.
8
7
  const TIER_ASSIGNMENT_NAMESPACE = "8e91d2fc-8b7a-4d3e-9f4a-1c5d6e7f8a9b";
9
8
 
10
9
  /**
11
- * Deterministic aggregate-id für ein Tier-Assignment aus dem tenantId.
12
- * Pro Plattform-Tenant existiert genau ein Aggregat — uuidv5 ist
13
- * namespace-deterministic, identische Eingabe ergibt identischen UUID.
10
+ * Deterministic aggregate ID for a tier assignment derived from `tenantId`.
11
+ * Each platform tenant has exactly one aggregate; uuidv5 is namespace-
12
+ * deterministic, so identical input produces the same UUID.
14
13
  *
15
- * **Wann nutzen:** Sprint 5 (`stripe-sync`-Feature) wrapt einen
16
- * idempotent-set-tier-Handler darum: zweiter Stripe-Webhook-Retry mit
17
- * derselben tenantId → derselbe aggregate-Stream → version_conflict
18
- * vom Event-Store statt pg-23505 von der Read-Model-DB. ES-saubere
19
- * Path-Uniqueness statt DB-Constraint.
14
+ * **When to use:** The `stripe-sync` feature wraps an idempotent
15
+ * set-tier handler with this function: a second Stripe webhook retry for
16
+ * the same `tenantId` targets the same aggregate stream, causing
17
+ * `version_conflict` from the event store instead of `pg-23505` from the
18
+ * read-model database. This enforces path uniqueness rather than a database
19
+ * constraint.
20
20
  *
21
- * **Sprint 1 nutzt das nicht aktiv** — Standard-CRUD-Handlers vergeben
22
- * UUID via `gen_random_uuid()`. Die Funktion lebt hier als Utility-
23
- * Export bereit für Sprint 5.
21
+ * Standard CRUD handlers instead generate UUIDs via `gen_random_uuid()`.
22
+ * This utility is exported for use by the `stripe-sync` feature.
24
23
  */
25
24
  // @wrapper-known uuid-domain
26
25
  export function tierAssignmentAggregateId(tenantId: string): string {