@cosmicdrift/kumiko-samples 0.386.0 → 0.388.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (530) 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 +9 -2
  5. package/packages/bundled-features/src/agent-tools/changes.json +6 -0
  6. package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
  7. package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +9 -9
  8. package/packages/bundled-features/src/audit/changes.json +12 -0
  9. package/packages/bundled-features/src/audit/handlers/audit-events.ts +1 -1
  10. package/packages/bundled-features/src/audit/screens.ts +1 -1
  11. package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +10 -10
  12. package/packages/bundled-features/src/auth-email-password/feature.ts +6 -6
  13. package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +3 -3
  14. package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
  15. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +1 -1
  16. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +18 -18
  17. package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +12 -12
  18. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
  19. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +24 -26
  20. package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +1 -1
  21. package/packages/bundled-features/src/auth-email-password/handlers/self-registration-status.query.ts +1 -1
  22. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +34 -37
  23. package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +6 -7
  24. package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +1 -5
  25. package/packages/bundled-features/src/auth-email-password/index.ts +5 -5
  26. package/packages/bundled-features/src/auth-email-password/lockout-store.ts +1 -1
  27. package/packages/bundled-features/src/auth-email-password/seeding.ts +63 -66
  28. package/packages/bundled-features/src/auth-email-password/signup-token-store.ts +8 -8
  29. package/packages/bundled-features/src/auth-email-password/testing.ts +3 -3
  30. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +57 -57
  31. package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +14 -14
  32. package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +15 -16
  33. package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +11 -12
  34. package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +1 -1
  35. package/packages/bundled-features/src/auth-email-password/web/constants.ts +3 -3
  36. package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +14 -14
  37. package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +11 -11
  38. package/packages/bundled-features/src/auth-email-password/web/index.ts +5 -5
  39. package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +17 -17
  40. package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +3 -4
  41. package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +16 -17
  42. package/packages/bundled-features/src/auth-email-password/web/session.tsx +34 -34
  43. package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +3 -3
  44. package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +14 -14
  45. package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +26 -27
  46. package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +12 -13
  47. package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +17 -18
  48. package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +11 -12
  49. package/packages/bundled-features/src/auth-foundation/boot-checks.ts +4 -4
  50. package/packages/bundled-features/src/auth-foundation/resolve-anonymous-access.ts +4 -4
  51. package/packages/bundled-features/src/auth-foundation/types.ts +2 -2
  52. package/packages/bundled-features/src/auth-mfa/changes.json +6 -0
  53. package/packages/bundled-features/src/auth-mfa/feature-exports.ts +2 -2
  54. package/packages/bundled-features/src/auth-mfa/feature.ts +6 -0
  55. package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +3 -3
  56. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +4 -4
  57. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +2 -2
  58. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  59. package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +1 -1
  60. package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -5
  61. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
  62. package/packages/bundled-features/src/auth-mfa/token-secrets.ts +1 -1
  63. package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +2 -2
  64. package/packages/bundled-features/src/auth-mfa/web/i18n.ts +9 -4
  65. package/packages/bundled-features/src/auth-mfa/web/index.ts +4 -4
  66. package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +17 -16
  67. package/packages/bundled-features/src/auth-mfa/web/mfa-code-or-recovery-field.tsx +68 -0
  68. package/packages/bundled-features/src/auth-mfa/web/mfa-disable-dialog.tsx +23 -13
  69. package/packages/bundled-features/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +23 -13
  70. package/packages/bundled-features/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +15 -6
  71. package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +71 -24
  72. package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
  73. package/packages/bundled-features/src/billing-foundation/changes.json +55 -0
  74. package/packages/bundled-features/src/billing-foundation/checkout-core.ts +32 -42
  75. package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +8 -2
  76. package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +2 -0
  77. package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +14 -3
  78. package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +3 -4
  79. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-receipt-limit.ts +12 -6
  80. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +35 -19
  81. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +12 -8
  82. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +14 -8
  83. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +5 -0
  84. package/packages/bundled-features/src/billing-foundation/consumer-protection/withdrawal-period.ts +8 -10
  85. package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
  86. package/packages/bundled-features/src/billing-foundation/events.ts +23 -21
  87. package/packages/bundled-features/src/billing-foundation/feature.ts +45 -44
  88. package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
  89. package/packages/bundled-features/src/billing-foundation/handlers/billing-plans.query.ts +71 -6
  90. package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +19 -17
  91. package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +11 -12
  92. package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -4
  93. package/packages/bundled-features/src/billing-foundation/handlers/plan-switch-preview.query.ts +65 -0
  94. package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +29 -22
  95. package/packages/bundled-features/src/billing-foundation/handlers/start-plan-checkout.write.ts +44 -8
  96. package/packages/bundled-features/src/billing-foundation/handlers/switch-plan.write.ts +72 -82
  97. package/packages/bundled-features/src/billing-foundation/handlers/sync-subscription.write.ts +14 -1
  98. package/packages/bundled-features/src/billing-foundation/i18n.ts +22 -0
  99. package/packages/bundled-features/src/billing-foundation/index.ts +2 -0
  100. package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +62 -27
  101. package/packages/bundled-features/src/billing-foundation/plan-switch.ts +84 -0
  102. package/packages/bundled-features/src/billing-foundation/projection.ts +38 -37
  103. package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -3
  104. package/packages/bundled-features/src/billing-foundation/tenant-destroy-hook.ts +7 -8
  105. package/packages/bundled-features/src/billing-foundation/types.ts +144 -66
  106. package/packages/bundled-features/src/billing-foundation/validate-options.ts +19 -0
  107. package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +123 -51
  108. package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +89 -42
  109. package/packages/bundled-features/src/billing-foundation/web/constants.ts +4 -0
  110. package/packages/bundled-features/src/billing-foundation/web/plan-price.ts +55 -0
  111. package/packages/bundled-features/src/billing-foundation/web/plan-switch-confirm-dialog.tsx +224 -0
  112. package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +1 -1
  113. package/packages/bundled-features/src/cap-counter/aggregate-id.ts +8 -9
  114. package/packages/bundled-features/src/cap-counter/cap-reservation.ts +5 -1
  115. package/packages/bundled-features/src/cap-counter/changes.json +18 -0
  116. package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
  117. package/packages/bundled-features/src/cap-counter/enforce-cap.ts +66 -68
  118. package/packages/bundled-features/src/cap-counter/entity.ts +29 -29
  119. package/packages/bundled-features/src/cap-counter/feature.ts +34 -35
  120. package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +31 -31
  121. package/packages/bundled-features/src/cap-counter/handlers/mark-soft-warned.write.ts +4 -5
  122. package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +9 -2
  123. package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +3 -5
  124. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -3
  125. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
  126. package/packages/bundled-features/src/channel-email/changes.json +6 -0
  127. package/packages/bundled-features/src/channel-email/feature.ts +1 -1
  128. package/packages/bundled-features/src/channel-email/smtp-transport.ts +34 -31
  129. package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +3 -4
  130. package/packages/bundled-features/src/compliance-profiles/feature.ts +15 -16
  131. package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +3 -6
  132. package/packages/bundled-features/src/compliance-profiles/handlers/list-profiles.query.ts +5 -5
  133. package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +4 -4
  134. package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +13 -14
  135. package/packages/bundled-features/src/compliance-profiles/handlers/sub-processors.query.ts +9 -11
  136. package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +7 -7
  137. package/packages/bundled-features/src/compliance-profiles/schema/profile-selection.ts +18 -23
  138. package/packages/bundled-features/src/compliance-profiles/seeding.ts +14 -15
  139. package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +3 -3
  140. package/packages/bundled-features/src/compliance-profiles-ops/index.ts +2 -2
  141. package/packages/bundled-features/src/config/changes.json +12 -0
  142. package/packages/bundled-features/src/config/handlers/cascade.query.ts +4 -2
  143. package/packages/bundled-features/src/config/handlers/readiness.query.ts +7 -7
  144. package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +4 -5
  145. package/packages/bundled-features/src/config/handlers/set.write.ts +4 -4
  146. package/packages/bundled-features/src/config/handlers/values.query.ts +4 -2
  147. package/packages/bundled-features/src/config/resolver.ts +4 -4
  148. package/packages/bundled-features/src/config/table.ts +10 -10
  149. package/packages/bundled-features/src/config/write-helpers.ts +28 -9
  150. package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
  151. package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +23 -21
  152. package/packages/bundled-features/src/custom-fields/aggregate-id.ts +16 -17
  153. package/packages/bundled-features/src/custom-fields/entity.ts +49 -47
  154. package/packages/bundled-features/src/custom-fields/events.ts +7 -8
  155. package/packages/bundled-features/src/custom-fields/feature.ts +70 -72
  156. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +9 -8
  157. package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +28 -26
  158. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +6 -7
  159. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +12 -13
  160. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +25 -28
  161. package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +6 -6
  162. package/packages/bundled-features/src/custom-fields/lib/field-access.ts +2 -2
  163. package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +1 -1
  164. package/packages/bundled-features/src/custom-fields/lib/quota.ts +1 -1
  165. package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -12
  166. package/packages/bundled-features/src/custom-fields/run-retention.ts +3 -3
  167. package/packages/bundled-features/src/custom-fields/schemas.ts +14 -14
  168. package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +2 -5
  169. package/packages/bundled-features/src/custom-fields/web/constants.ts +2 -2
  170. package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +26 -26
  171. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +65 -67
  172. package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +3 -3
  173. package/packages/bundled-features/src/data-retention/_internal/parse-override.ts +2 -3
  174. package/packages/bundled-features/src/data-retention/feature.ts +11 -18
  175. package/packages/bundled-features/src/data-retention/handlers/policy-for.query.ts +6 -6
  176. package/packages/bundled-features/src/data-retention/keep-for.ts +17 -17
  177. package/packages/bundled-features/src/data-retention/override-schema.ts +13 -15
  178. package/packages/bundled-features/src/data-retention/presets.ts +18 -23
  179. package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
  180. package/packages/bundled-features/src/data-retention/resolve-tenant-preset.ts +17 -16
  181. package/packages/bundled-features/src/data-retention/resolver.ts +33 -32
  182. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +71 -58
  183. package/packages/bundled-features/src/data-retention/schema/tenant-retention-override.ts +13 -11
  184. package/packages/bundled-features/src/delivery/changes.json +30 -0
  185. package/packages/bundled-features/src/delivery/channel-context.ts +9 -3
  186. package/packages/bundled-features/src/delivery/db/queries/preferences.ts +2 -2
  187. package/packages/bundled-features/src/delivery/delivery-service.ts +35 -5
  188. package/packages/bundled-features/src/delivery/feature.ts +3 -3
  189. package/packages/bundled-features/src/delivery/handlers/log.query.ts +1 -1
  190. package/packages/bundled-features/src/delivery/handlers/preferences.query.ts +20 -1
  191. package/packages/bundled-features/src/delivery/handlers/unsubscribe-page-chrome.query.ts +1 -1
  192. package/packages/bundled-features/src/delivery/tables.ts +9 -8
  193. package/packages/bundled-features/src/delivery/unsubscribe-link.ts +3 -1
  194. package/packages/bundled-features/src/delivery/unsubscribe-page-strings.ts +1 -0
  195. package/packages/bundled-features/src/delivery/unsubscribe-page.ts +6 -0
  196. package/packages/bundled-features/src/delivery/unsubscribe.ts +40 -19
  197. package/packages/bundled-features/src/delivery/upsert-preference.ts +3 -4
  198. package/packages/bundled-features/src/document-ingest-foundation/entity.ts +5 -5
  199. package/packages/bundled-features/src/document-ingest-foundation/events.ts +2 -2
  200. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +2 -2
  201. package/packages/bundled-features/src/document-ingest-foundation/pages.ts +1 -1
  202. package/packages/bundled-features/src/document-ingest-foundation/tenant-destroy-hook.ts +4 -4
  203. package/packages/bundled-features/src/feature-toggles/compose-tier-resolver.ts +1 -1
  204. package/packages/bundled-features/src/feature-toggles/feature.ts +1 -1
  205. package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
  206. package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +5 -5
  207. package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
  208. package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
  209. package/packages/bundled-features/src/feature-toggles/web/constants.ts +1 -1
  210. package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
  211. package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
  212. package/packages/bundled-features/src/file-derivatives/presets.ts +1 -1
  213. package/packages/bundled-features/src/file-foundation/feature.ts +6 -6
  214. package/packages/bundled-features/src/file-foundation/index.ts +1 -0
  215. package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +7 -1
  216. package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
  217. package/packages/bundled-features/src/file-provider-s3/env-named-feature.ts +0 -2
  218. package/packages/bundled-features/src/file-provider-s3/feature.ts +16 -16
  219. package/packages/bundled-features/src/file-provider-s3/lib/s3-provider.ts +6 -6
  220. package/packages/bundled-features/src/files/README.md +1 -1
  221. package/packages/bundled-features/src/files/feature.ts +6 -6
  222. package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +5 -5
  223. package/packages/bundled-features/src/files-tenant-data/hooks.ts +24 -26
  224. package/packages/bundled-features/src/files-tenant-data/index.ts +1 -1
  225. package/packages/bundled-features/src/folders/feature.ts +1 -1
  226. package/packages/bundled-features/src/folders/web/folder-manager.tsx +2 -2
  227. package/packages/bundled-features/src/folders/web/tree.ts +5 -5
  228. package/packages/bundled-features/src/form-draft/changes.json +6 -0
  229. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +3 -3
  230. package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
  231. package/packages/bundled-features/src/form-draft/decrypt-draft.ts +4 -1
  232. package/packages/bundled-features/src/form-draft/entity.ts +3 -3
  233. package/packages/bundled-features/src/form-draft/feature.ts +4 -5
  234. package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
  235. package/packages/bundled-features/src/form-draft/release-file-refs.ts +6 -6
  236. package/packages/bundled-features/src/form-draft/schemas.ts +3 -3
  237. package/packages/bundled-features/src/form-draft/web/constants.ts +0 -2
  238. package/packages/bundled-features/src/host-routing/README.md +1 -1
  239. package/packages/bundled-features/src/host-routing/changes.json +6 -0
  240. package/packages/bundled-features/src/host-routing/dispatch.ts +16 -17
  241. package/packages/bundled-features/src/host-routing/options.ts +2 -1
  242. package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
  243. package/packages/bundled-features/src/inbound-mail-foundation/changes.json +18 -0
  244. package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +4 -3
  245. package/packages/bundled-features/src/inbound-mail-foundation/constants.ts +30 -33
  246. package/packages/bundled-features/src/inbound-mail-foundation/entities.ts +47 -48
  247. package/packages/bundled-features/src/inbound-mail-foundation/events.ts +54 -50
  248. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +39 -39
  249. package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +8 -8
  250. package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +25 -26
  251. package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +7 -7
  252. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +50 -51
  253. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +8 -8
  254. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +10 -10
  255. package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +3 -4
  256. package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +27 -15
  257. package/packages/bundled-features/src/inbound-mail-foundation/i18n.ts +0 -1
  258. package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +16 -15
  259. package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +31 -29
  260. package/packages/bundled-features/src/inbound-mail-foundation/provider-factory.ts +9 -9
  261. package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +45 -41
  262. package/packages/bundled-features/src/inbound-mail-foundation/screens.ts +0 -3
  263. package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
  264. package/packages/bundled-features/src/inbound-mail-foundation/types.ts +70 -70
  265. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +101 -84
  266. package/packages/bundled-features/src/inbound-provider-imap/credential-document.ts +13 -13
  267. package/packages/bundled-features/src/inbound-provider-imap/feature.ts +42 -40
  268. package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +20 -19
  269. package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +21 -21
  270. package/packages/bundled-features/src/jobs/changes.json +13 -0
  271. package/packages/bundled-features/src/jobs/db/queries/retention.ts +2 -2
  272. package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +3 -3
  273. package/packages/bundled-features/src/jobs/events.ts +1 -1
  274. package/packages/bundled-features/src/jobs/feature.ts +20 -11
  275. package/packages/bundled-features/src/jobs/handlers/detail.query.ts +4 -4
  276. package/packages/bundled-features/src/jobs/handlers/list.query.ts +1 -1
  277. package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
  278. package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +1 -1
  279. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  280. package/packages/bundled-features/src/jobs/handlers/tenant-failures.query.ts +45 -40
  281. package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +63 -59
  282. package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
  283. package/packages/bundled-features/src/jobs/job-run-logger.ts +19 -19
  284. package/packages/bundled-features/src/jobs/job-run-table.ts +3 -3
  285. package/packages/bundled-features/src/jobs/screens.ts +1 -1
  286. package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
  287. package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
  288. package/packages/bundled-features/src/ledger/entity.ts +5 -5
  289. package/packages/bundled-features/src/ledger/feature.ts +3 -3
  290. package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +3 -3
  291. package/packages/bundled-features/src/ledger/recurring.ts +12 -12
  292. package/packages/bundled-features/src/ledger/schemas.ts +1 -1
  293. package/packages/bundled-features/src/ledger/web/constants.ts +2 -2
  294. package/packages/bundled-features/src/ledger/web/index.ts +7 -7
  295. package/packages/bundled-features/src/legal-pages/README.md +1 -1
  296. package/packages/bundled-features/src/legal-pages/feature.ts +40 -41
  297. package/packages/bundled-features/src/legal-pages/markdown.ts +3 -3
  298. package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +23 -24
  299. package/packages/bundled-features/src/legal-pages/web/index.ts +0 -2
  300. package/packages/bundled-features/src/mail-foundation/changes.json +6 -0
  301. package/packages/bundled-features/src/mail-foundation/feature.ts +31 -30
  302. package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +27 -28
  303. package/packages/bundled-features/src/mail-transport-smtp/feature.ts +20 -20
  304. package/packages/bundled-features/src/managed-pages/branding.ts +6 -6
  305. package/packages/bundled-features/src/managed-pages/feature.ts +62 -62
  306. package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +5 -6
  307. package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +8 -8
  308. package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +5 -7
  309. package/packages/bundled-features/src/managed-pages/screens/page-screens.ts +11 -11
  310. package/packages/bundled-features/src/managed-pages/seeding.ts +8 -8
  311. package/packages/bundled-features/src/managed-pages/table.ts +16 -15
  312. package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +6 -6
  313. package/packages/bundled-features/src/managed-pages/web/i18n.ts +1 -1
  314. package/packages/bundled-features/src/notes-history/entity.ts +4 -4
  315. package/packages/bundled-features/src/notes-history/feature.ts +2 -2
  316. package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
  317. package/packages/bundled-features/src/page-render/layout.ts +9 -9
  318. package/packages/bundled-features/src/page-render/markdown.ts +11 -11
  319. package/packages/bundled-features/src/page-render/security-headers.ts +7 -6
  320. package/packages/bundled-features/src/personal-access-tokens/feature.ts +9 -6
  321. package/packages/bundled-features/src/personal-access-tokens/roles.ts +2 -2
  322. package/packages/bundled-features/src/readiness/handlers/status.query.ts +3 -3
  323. package/packages/bundled-features/src/renderer-foundation/api.ts +12 -13
  324. package/packages/bundled-features/src/renderer-foundation/constants.ts +2 -2
  325. package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
  326. package/packages/bundled-features/src/renderer-foundation/types.ts +11 -12
  327. package/packages/bundled-features/src/renderer-pdf/changes.json +6 -0
  328. package/packages/bundled-features/src/renderer-pdf/render-table-pdf.ts +27 -10
  329. package/packages/bundled-features/src/secrets/feature.ts +9 -9
  330. package/packages/bundled-features/src/secrets/web/constants.ts +2 -2
  331. package/packages/bundled-features/src/seo/feature.ts +3 -3
  332. package/packages/bundled-features/src/sessions/constants.ts +1 -1
  333. package/packages/bundled-features/src/sessions/feature.ts +16 -11
  334. package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +2 -2
  335. package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +2 -2
  336. package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
  337. package/packages/bundled-features/src/sessions/schema/user-session.ts +4 -4
  338. package/packages/bundled-features/src/sessions/screens.ts +2 -2
  339. package/packages/bundled-features/src/sessions/session-callbacks.ts +2 -2
  340. package/packages/bundled-features/src/sessions/session-revoked-event.ts +2 -2
  341. package/packages/bundled-features/src/shared/assert-no-where-rule-in-ownership-write.ts +1 -1
  342. package/packages/bundled-features/src/shared/decrypt-stored-pii.ts +11 -1
  343. package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
  344. package/packages/bundled-features/src/shared/index.ts +1 -1
  345. package/packages/bundled-features/src/shared/mail-template-body.ts +10 -3
  346. package/packages/bundled-features/src/shared/map-with-concurrency.ts +5 -4
  347. package/packages/bundled-features/src/shared/parent-visibility.ts +2 -2
  348. package/packages/bundled-features/src/shared/password-hashing.ts +1 -1
  349. package/packages/bundled-features/src/shared/signup-handover.ts +1 -2
  350. package/packages/bundled-features/src/shared/single-use-token-store.ts +1 -1
  351. package/packages/bundled-features/src/step-dispatcher/changes.json +6 -0
  352. package/packages/bundled-features/src/step-dispatcher/feature.ts +1 -0
  353. package/packages/bundled-features/src/subscription-dodo/changes.json +14 -0
  354. package/packages/bundled-features/src/subscription-dodo/client.ts +45 -0
  355. package/packages/bundled-features/src/subscription-dodo/constants.ts +24 -0
  356. package/packages/bundled-features/src/subscription-dodo/feature.ts +207 -0
  357. package/packages/bundled-features/src/subscription-dodo/index.ts +16 -0
  358. package/packages/bundled-features/src/subscription-dodo/plugin-methods.ts +345 -0
  359. package/packages/bundled-features/src/subscription-dodo/runtime.ts +126 -0
  360. package/packages/bundled-features/src/subscription-dodo/verify-webhook.ts +262 -0
  361. package/packages/bundled-features/src/subscription-mollie/constants.ts +15 -17
  362. package/packages/bundled-features/src/subscription-mollie/feature.ts +41 -42
  363. package/packages/bundled-features/src/subscription-mollie/index.ts +3 -3
  364. package/packages/bundled-features/src/subscription-mollie/plugin-methods.ts +17 -16
  365. package/packages/bundled-features/src/subscription-mollie/verify-webhook.ts +34 -34
  366. package/packages/bundled-features/src/subscription-stripe/changes.json +12 -0
  367. package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
  368. package/packages/bundled-features/src/subscription-stripe/feature.ts +45 -43
  369. package/packages/bundled-features/src/subscription-stripe/index.ts +6 -6
  370. package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +22 -27
  371. package/packages/bundled-features/src/subscription-stripe/runtime.ts +9 -8
  372. package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +62 -64
  373. package/packages/bundled-features/src/tags/feature.ts +3 -3
  374. package/packages/bundled-features/src/tags/screens.ts +1 -1
  375. package/packages/bundled-features/src/template-resolver/api.ts +41 -14
  376. package/packages/bundled-features/src/template-resolver/changes.json +48 -0
  377. package/packages/bundled-features/src/template-resolver/compile-document-body.ts +1 -0
  378. package/packages/bundled-features/src/template-resolver/feature.ts +2 -2
  379. package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +3 -2
  380. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +27 -5
  381. package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +3 -2
  382. package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +3 -2
  383. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +8 -7
  384. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +19 -20
  385. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +15 -5
  386. package/packages/bundled-features/src/template-resolver/handlers/shared.ts +2 -2
  387. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +3 -3
  388. package/packages/bundled-features/src/template-resolver/handlers/tenant-override-counts.query.ts +9 -5
  389. package/packages/bundled-features/src/template-resolver/handlers/tenant-override-selection.ts +8 -6
  390. package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +44 -5
  391. package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +3 -4
  392. package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +4 -5
  393. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +37 -26
  394. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +7 -2
  395. package/packages/bundled-features/src/template-resolver/seeding.ts +36 -18
  396. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +22 -4
  397. package/packages/bundled-features/src/template-resolver/table.ts +13 -14
  398. package/packages/bundled-features/src/template-resolver/template-delivery-policy.ts +0 -11
  399. package/packages/bundled-features/src/template-resolver/template-meta.ts +12 -4
  400. package/packages/bundled-features/src/template-resolver/template-preview.ts +11 -3
  401. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
  402. package/packages/bundled-features/src/template-resolver/web/constants.ts +7 -5
  403. package/packages/bundled-features/src/template-resolver/web/index.ts +7 -0
  404. package/packages/bundled-features/src/template-resolver/web/mail-layout-constants.ts +8 -0
  405. package/packages/bundled-features/src/tenant/changes.json +6 -0
  406. package/packages/bundled-features/src/tenant/feature.ts +7 -7
  407. package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +10 -4
  408. package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
  409. package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
  410. package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
  411. package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +8 -5
  412. package/packages/bundled-features/src/tenant/invitation-table.ts +37 -40
  413. package/packages/bundled-features/src/tenant/membership-table.ts +3 -3
  414. package/packages/bundled-features/src/tenant/schema/tenant.ts +7 -9
  415. package/packages/bundled-features/src/tenant/screens.ts +1 -1
  416. package/packages/bundled-features/src/tenant/seeding.ts +19 -18
  417. package/packages/bundled-features/src/tenant/testing.ts +5 -6
  418. package/packages/bundled-features/src/tenant/web/constants.ts +2 -2
  419. package/packages/bundled-features/src/tenant-handover/events.ts +5 -7
  420. package/packages/bundled-features/src/tenant-handover/feature.ts +1 -1
  421. package/packages/bundled-features/src/tenant-handover/grant.ts +1 -1
  422. package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
  423. package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +8 -9
  424. package/packages/bundled-features/src/tenant-handover/signup-handover-provider.ts +1 -2
  425. package/packages/bundled-features/src/tenant-handover/transfer-graph.ts +4 -5
  426. package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
  427. package/packages/bundled-features/src/tenant-lifecycle/changes.json +6 -0
  428. package/packages/bundled-features/src/tenant-lifecycle/constants.ts +5 -0
  429. package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
  430. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +7 -3
  431. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +1 -1
  432. package/packages/bundled-features/src/tenant-settings/constants.ts +1 -1
  433. package/packages/bundled-features/src/tenant-settings/tenant-defaults.ts +12 -5
  434. package/packages/bundled-features/src/tier-engine/aggregate-id.ts +15 -16
  435. package/packages/bundled-features/src/tier-engine/changes.json +6 -0
  436. package/packages/bundled-features/src/tier-engine/compose-app.ts +14 -14
  437. package/packages/bundled-features/src/tier-engine/entity.ts +18 -19
  438. package/packages/bundled-features/src/tier-engine/feature.ts +88 -87
  439. package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +6 -7
  440. package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +4 -4
  441. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +12 -9
  442. package/packages/bundled-features/src/tier-engine/tier-resolver.ts +2 -2
  443. package/packages/bundled-features/src/tier-engine/trial.ts +13 -13
  444. package/packages/bundled-features/src/tier-engine/web/constants.ts +3 -3
  445. package/packages/bundled-features/src/tier-engine/web/index.ts +4 -4
  446. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +8 -8
  447. package/packages/bundled-features/src/user/handlers/create.write.ts +4 -4
  448. package/packages/bundled-features/src/user/schema/user.ts +45 -44
  449. package/packages/bundled-features/src/user/seeding.ts +40 -40
  450. package/packages/bundled-features/src/user/testing.ts +3 -3
  451. package/packages/bundled-features/src/user-data-rights/audit-download.ts +27 -28
  452. package/packages/bundled-features/src/user-data-rights/boot-checks.ts +1 -1
  453. package/packages/bundled-features/src/user-data-rights/deletion-token.ts +1 -1
  454. package/packages/bundled-features/src/user-data-rights/feature.ts +112 -113
  455. package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +9 -9
  456. package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +8 -8
  457. package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +29 -30
  458. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +40 -42
  459. package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +8 -9
  460. package/packages/bundled-features/src/user-data-rights/handlers/lift-restriction.write.ts +7 -8
  461. package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +2 -2
  462. package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +4 -4
  463. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion-by-email.write.ts +30 -29
  464. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +15 -18
  465. package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +42 -41
  466. package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +22 -19
  467. package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +8 -8
  468. package/packages/bundled-features/src/user-data-rights/index.ts +8 -10
  469. package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +3 -3
  470. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +24 -27
  471. package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +169 -280
  472. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +87 -108
  473. package/packages/bundled-features/src/user-data-rights/run-user-export.ts +67 -69
  474. package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +11 -11
  475. package/packages/bundled-features/src/user-data-rights/schema/download-token.ts +37 -41
  476. package/packages/bundled-features/src/user-data-rights/schema/export-job.ts +65 -67
  477. package/packages/bundled-features/src/user-data-rights/token-helpers.ts +21 -25
  478. package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +6 -6
  479. package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +6 -5
  480. package/packages/bundled-features/src/user-data-rights/web/constants.ts +1 -1
  481. package/packages/bundled-features/src/user-data-rights/web/index.ts +5 -5
  482. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +14 -13
  483. package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +13 -12
  484. package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +6 -6
  485. package/packages/bundled-features/src/user-data-rights/zip-path.ts +41 -40
  486. package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +15 -15
  487. package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +3 -5
  488. package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +45 -51
  489. package/packages/bundled-features/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +2 -2
  490. package/packages/bundled-features/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +1 -1
  491. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +3 -3
  492. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +32 -31
  493. package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +13 -13
  494. package/packages/bundled-features/src/user-profile/index.ts +3 -3
  495. package/packages/bundled-features/src/user-profile/web/client-plugin.ts +1 -1
  496. package/packages/bundled-features/src/user-profile/web/constants.ts +1 -1
  497. package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +1 -1
  498. package/packages/bundled-features/src/waitlist/changes.json +18 -0
  499. package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +2 -1
  500. package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +5 -5
  501. package/packages/bundled-features/src/waitlist/import.ts +5 -0
  502. package/packages/bundled-features/src/waitlist/legacy-migrate.ts +22 -3
  503. package/packages/bundled-features/src/waitlist/link-on-signup.ts +20 -10
  504. package/packages/bundled-features/src/waitlist/options.ts +3 -0
  505. package/packages/bundled-features/src/workflow-runner/aggregate-id.ts +1 -1
  506. package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -5
  507. package/packages/bundled-features/src/workflow-runner/event-trigger.ts +4 -15
  508. package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
  509. package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +4 -4
  510. package/packages/bundled-features/src/workflow-runner/pending-projection.ts +6 -7
  511. package/packages/bundled-features/src/workflow-runner/runner.ts +6 -6
  512. package/packages/bundled-features/src/workflow-runner/tables.ts +6 -6
  513. package/packages/bundled-features/src/workflow-runner/workflow-registry.ts +1 -1
  514. package/samples/apps/styleguide/src/features/widgets/i18n.ts +11 -0
  515. package/samples/apps/styleguide/src/features/widgets/web/Widgets.tsx +24 -0
  516. package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-constants.ts +5 -0
  517. package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +90 -15
  518. package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +16 -6
  519. package/samples/apps/use-all-bundled/feature-manifest.json +120 -3
  520. package/samples/apps/use-all-bundled/src/run-config.ts +9 -3
  521. package/samples/recipes/auth-mfa/README.md +5 -0
  522. package/samples/recipes/auth-mfa/package.json +5 -2
  523. package/samples/recipes/auth-mfa/src/web/confirmation-code-step.tsx +49 -0
  524. package/samples/recipes/auth-mfa/tsconfig.json +8 -0
  525. package/samples/recipes/env-composition/README.md +3 -1
  526. package/samples/recipes/env-composition/src/env.ts +2 -0
  527. package/samples/recipes/legal-pages/README.md +1 -1
  528. package/samples/recipes/rate-limiting/README.md +18 -0
  529. package/samples/recipes/rate-limiting/src/feature.ts +12 -0
  530. package/packages/bundled-features/src/billing-foundation/consumer-protection/stored-user-email.ts +0 -12
@@ -74,7 +74,8 @@ export const setWrite = defineWriteHandler({
74
74
  // rejected), but an admin override write can still target scope=
75
75
  // "system" for a tenant/user-scoped key (validateScope allows any
76
76
  // requestedScope <= definedScope) — system-row has no subject.
77
- if (keyDef.piiEncrypted && scope === ConfigScopes.system) {
77
+ const piiScope = keyDef.piiEncrypted && scope !== ConfigScopes.system ? scope : undefined;
78
+ if (keyDef.piiEncrypted && piiScope === undefined) {
78
79
  return writeFailure(
79
80
  new UnprocessableError("invalid_scope", {
80
81
  i18nKey: "config.errors.invalidScope",
@@ -153,7 +154,7 @@ export const setWrite = defineWriteHandler({
153
154
  if (keyDef.encrypted) {
154
155
  const cipher = requireConfigEncryption(ctx, "config:write:set");
155
156
  serialized = await cipher.encrypt(serialized, { tenantId });
156
- } else if (keyDef.piiEncrypted) {
157
+ } else if (piiScope !== undefined) {
157
158
  const kms = configuredPiiSubjectKms();
158
159
  if (!kms) {
159
160
  throw new InternalError({
@@ -163,8 +164,7 @@ export const setWrite = defineWriteHandler({
163
164
  `configurePiiSubjectKms(adapter) at boot.`,
164
165
  });
165
166
  }
166
- // scope="system" was already rejected above — narrow accordingly.
167
- const subject = resolvePiiSubject(scope as Exclude<typeof scope, "system">, tenantId, userId);
167
+ const subject = resolvePiiSubject(piiScope, tenantId, userId);
168
168
  const kmsCtx: KmsContext = {
169
169
  requestId: requestContext.get()?.requestId ?? "config:write:set",
170
170
  tenantId,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  type ConfigKeyDefinition,
3
3
  type ConfigScope,
4
+ ConfigScopes,
4
5
  type ConfigValueSource,
5
6
  defineQueryHandler,
6
7
  isEncryptedAtRest,
@@ -8,7 +9,7 @@ import {
8
9
  import * as z from "zod";
9
10
  import { requireConfigResolver, requireSystemDb } from "../feature.ts";
10
11
  import { MASKED, redactInheritedCascade, shouldRedactInherited } from "../read-redaction.ts";
11
- import { hasConfigAccess } from "../write-helpers.ts";
12
+ import { hasConfigAccess, keyDefAtScope } from "../write-helpers.ts";
12
13
 
13
14
  export const valuesQuery = defineQueryHandler({
14
15
  name: "values",
@@ -16,6 +17,7 @@ export const valuesQuery = defineQueryHandler({
16
17
  "Returns the effective value, scope and winning source for every config key the caller may read (optionally narrowed to `keys`), with encrypted and secret-backed values masked; use it to inspect the current settings.",
17
18
  schema: z.object({
18
19
  keys: z.array(z.string()).optional(),
20
+ scope: z.enum([ConfigScopes.system, ConfigScopes.tenant, ConfigScopes.user]).optional(),
19
21
  }),
20
22
  // Per-key read access enforced via hasConfigAccess inside the handler.
21
23
  access: {
@@ -44,7 +46,7 @@ export const valuesQuery = defineQueryHandler({
44
46
  for (const [qualifiedKey, keyDef] of allKeys) {
45
47
  if (requestedKeys !== undefined && !requestedKeys.has(qualifiedKey)) continue;
46
48
  if (!hasConfigAccess(keyDef.access.read, query.user.roles)) continue;
47
- keyDefs.set(qualifiedKey, keyDef);
49
+ keyDefs.set(qualifiedKey, keyDefAtScope(keyDef, query.payload.scope, query.user.roles));
48
50
  filteredKeys.push(qualifiedKey);
49
51
  }
50
52
 
@@ -583,10 +583,10 @@ export function validateAppOverrides(
583
583
  );
584
584
  }
585
585
 
586
- // Per keyDef.type narrow value inline — TS narrowt nicht durch
587
- // `typeof value !== typeForKey(...)` (typeForKey returnt string,
588
- // kein discriminator). Das vermeidet `value as string|number` casts
589
- // unten, weil value innerhalb des Branches schon typed ist.
586
+ // Narrow by keyDef.type inline because TypeScript cannot narrow through
587
+ // `typeof value !== typeForKey(...)`, whose return type is string rather
588
+ // than a discriminator. This avoids `value as string|number` casts below;
589
+ // value is correctly typed within each branch.
590
590
  if (keyDef.type === "number") {
591
591
  if (typeof value !== "number") {
592
592
  throw new Error(`App-Boot-Override for "${key}": expected number, got ${typeof value}`);
@@ -3,19 +3,19 @@ import { createEntity, createTextField } from "@cosmicdrift/kumiko-framework/eng
3
3
 
4
4
  // Config values are event-sourced. Each (key, scope) is its own aggregate
5
5
  // stream — lifecycle events `configValue.created / .updated / .deleted`
6
- // flow through createEventStoreExecutor, which writes the stream + this
7
- // projection in one TX. Reads stay O(1) against the projection.
6
+ // flow through createEventStoreExecutor, which writes the stream and this
7
+ // projection in one TX. Reads remain O(1) against the projection.
8
8
  //
9
9
  // System-scope rows use SYSTEM_TENANT_ID (not null) — buildBaseColumns
10
- // (via buildEntityTable) forces tenant_id NOT NULL, so die pre-ES "NULL
11
- // means system" convention is replaced with a fixed sentinel. Der unique
12
- // index über (key, tenant_id, user_id) prevent duplicate writes at the DB
13
- // level — deklariert via entity.indexes.
10
+ // (via buildEntityTable) forces tenant_id NOT NULL, so the pre-ES "NULL
11
+ // means system" convention is replaced with a fixed sentinel. The unique
12
+ // index on (key, tenant_id, user_id) prevents duplicate writes at the DB
13
+ // level — declared via entity.indexes.
14
14
  //
15
- // Single-Source-of-Truth: `configValueEntity`. Die DB-Tabelle wird über
16
- // buildEntityTable aus der EntityDefinition abgeleitet, der unique-Index
17
- // ist via entity.indexes deklariert. Plural-Re-Export `configValuesTable`
18
- // dient handlers (`reset.write.ts` etc.) als typisierte Drizzle-Table-Ref.
15
+ // Single source of truth: `configValueEntity`. The DB table is derived from
16
+ // the EntityDefinition through buildEntityTable, and the unique index is
17
+ // declared via entity.indexes. The plural re-export `configValuesTable`
18
+ // provides handlers (`reset.write.ts` etc.) with a typed Drizzle table ref.
19
19
  export const configValueEntity = createEntity({
20
20
  table: "read_config_values",
21
21
  fields: {
@@ -75,8 +75,9 @@ export async function configRowHoldsValue(
75
75
  serializedValue: string,
76
76
  ): Promise<boolean> {
77
77
  if (row?.value === null || row?.value === undefined) return false;
78
- if (!keyDef?.encrypted && !keyDef?.piiEncrypted) return row.value === serializedValue;
79
- if (!keyDef) return false;
78
+ if (keyDef === undefined || (!keyDef.encrypted && !keyDef.piiEncrypted)) {
79
+ return row.value === serializedValue;
80
+ }
80
81
  try {
81
82
  return (await decryptStoredValue(row.value, keyDef, cipher, qualifiedKey)) === serializedValue;
82
83
  } catch {
@@ -194,12 +195,7 @@ export function validateScope(
194
195
  definedScope: ConfigScope,
195
196
  key: string,
196
197
  ): KumikoError | null {
197
- const levels: Record<ConfigScope, number> = {
198
- [ConfigScopes.system]: 0,
199
- [ConfigScopes.tenant]: 1,
200
- [ConfigScopes.user]: 2,
201
- };
202
- if (levels[requestedScope] > levels[definedScope]) {
198
+ if (SCOPE_LEVEL[requestedScope] > SCOPE_LEVEL[definedScope]) {
203
199
  return new UnprocessableError("invalid_scope", {
204
200
  i18nKey: "config.errors.invalidScope",
205
201
  details: { key, definedScope, requestedScope },
@@ -208,6 +204,29 @@ export function validateScope(
208
204
  return null;
209
205
  }
210
206
 
207
+ const SCOPE_LEVEL: Record<ConfigScope, number> = {
208
+ [ConfigScopes.system]: 0,
209
+ [ConfigScopes.tenant]: 1,
210
+ [ConfigScopes.user]: 2,
211
+ };
212
+
213
+ // Reads a tenant/user key at a narrower scope, e.g. system for a system-level screen.
214
+ // Only a SystemAdmin may widen the read to the platform level; everyone else keeps the normal cascade.
215
+ export function keyDefAtScope(
216
+ keyDef: ConfigKeyDefinition,
217
+ readScope: ConfigScope | undefined,
218
+ roles: readonly string[],
219
+ ): ConfigKeyDefinition {
220
+ if (
221
+ readScope === undefined ||
222
+ !roles.includes("SystemAdmin") ||
223
+ SCOPE_LEVEL[readScope] >= SCOPE_LEVEL[keyDef.scope]
224
+ ) {
225
+ return keyDef;
226
+ }
227
+ return { ...keyDef, scope: readScope };
228
+ }
229
+
211
230
  export function resolveScopeIds(
212
231
  scope: ConfigScope,
213
232
  tenantId: TenantId,
@@ -226,7 +245,7 @@ export function resolveScopeIds(
226
245
  }
227
246
 
228
247
  // The subject a piiEncrypted config value is encrypted under, for the scope
229
- // actually written to (kumiko-platform#231/#459). Pure — no I/O — so a bug
248
+ // actually written to. Pure — no I/O — so a bug
230
249
  // here (e.g. picking the writer's identity instead of the row's target,
231
250
  // see entity fields' explicit userOwned.ownerField for why that
232
251
  // distinction matters) is caught by a fast unit test, not only the DB-
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.388.0",
4
+ "type": "fix",
5
+ "title": "forget-subject audit event survives a failing record owner lookup",
6
+ "detail": "The lookup of the record row's owning tenant now runs inside the file purge step, so a database error there is reported as cleanupError on the subject-forgotten event instead of aborting the handler after the key was erased."
7
+ },
2
8
  {
3
9
  "version": "0.377.0",
4
10
  "type": "fix",
@@ -112,7 +112,7 @@ function subjectAggregateId(raw: SubjectIdInput): string {
112
112
  }
113
113
 
114
114
  // The record subject names its own entity — resolve it against the registry
115
- // instead of trusting the payload straight into resolveTableName/SQL (#2786).
115
+ // instead of trusting the payload straight into resolveTableName/SQL.
116
116
  function findRegisteredEntity(
117
117
  features: ReadonlyMap<string, FeatureDefinition>,
118
118
  entityName: string,
@@ -124,7 +124,7 @@ function findRegisteredEntity(
124
124
  return undefined;
125
125
  }
126
126
 
127
- // Tenant-scope guard (mh#349): DataProtectionOfficer is a tenant-scoped role,
127
+ // Tenant-scope guard: DataProtectionOfficer is a tenant-scoped role,
128
128
  // but the handler otherwise erases ANY subject cross-tenant on a raw
129
129
  // (un-scoped) client — a Tenant-A DPO who learns a Tenant-B subject id
130
130
  // (export, support ticket, log line) could destroy it. SystemAdmin
@@ -182,7 +182,7 @@ async function resolveTenantScopeDenial(
182
182
  return ownedInTenant ? undefined : memberDenied;
183
183
  }
184
184
 
185
- // fw#2789/#2805: blockDelete (legally mandated physical retention, e.g.
185
+ // blockDelete (legally mandated physical retention, e.g.
186
186
  // ledger/invoice text) means this command must refuse, not silently
187
187
  // anonymize or proceed. Refused when the host entity itself declares
188
188
  // blockDelete OR the owning tenant's effective data-retention policy
@@ -213,7 +213,7 @@ async function resolveRetentionDenial(
213
213
  const effective = await resolveRetentionPolicyForTenant({
214
214
  db: runner,
215
215
  registry: ctx.registry,
216
- tenantId: owningTenantId as TenantId,
216
+ tenantId: owningTenantId,
217
217
  entityName: raw.entity,
218
218
  });
219
219
  return effective.policy?.strategy === "blockDelete" ? deny() : undefined;
@@ -241,8 +241,8 @@ function denialReasonOf(failure: WriteFailure): string {
241
241
  return failure.error.code;
242
242
  }
243
243
 
244
- // Denied cross-tenant probes must still leave an audit trail (fw#2348).
245
- // Appended outside the handler tx (fw#2592): the caller's
244
+ // Denied cross-tenant probes must still leave an audit trail.
245
+ // Appended outside the handler tx: the caller's
246
246
  // `return tenantScopeDenial` rolls that tx back.
247
247
  async function appendDenialAuditEvent(
248
248
  ctx: HandlerContext,
@@ -285,7 +285,7 @@ async function appendDenialAuditEvent(
285
285
  registry: ctx.registry,
286
286
  db: denialAuditRunner,
287
287
  // MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw
288
- // bypasses TenantDb's scoping, so this is the only guard against a cross-tenant denial event (fw#2452).
288
+ // bypasses TenantDb's scoping, so this is the only guard against a cross-tenant denial event.
289
289
  tenantId: event.user.tenantId,
290
290
  userId: String(event.user.id),
291
291
  callSiteLabel: "forget-subject denial audit",
@@ -324,11 +324,6 @@ async function sweepDerivedSubjectData(
324
324
  audit: { readonly requestId: string; readonly erasedBy: string },
325
325
  rawSubject: SubjectIdInput,
326
326
  ): Promise<string | undefined> {
327
- const recordTenantId = await owningTenantOfRecordSubject(
328
- crossTenantRunner,
329
- ctx.registry.features,
330
- rawSubject,
331
- );
332
327
  const failureLabels: string[] = [];
333
328
  const runStep = async (step: (runner: DbRunner) => Promise<void>): Promise<void> => {
334
329
  try {
@@ -339,11 +334,11 @@ async function sweepDerivedSubjectData(
339
334
  };
340
335
 
341
336
  await runStep(async (crossTenantSubjectRunner) => {
342
- // Blind-index sweep (#818): nulls bidx columns now so the deterministic
337
+ // Blind-index sweep: nulls bidx columns now so the deterministic
343
338
  // HMAC doesn't stay equality-matchable; raw because the ciphertext prefix addresses the subject across tenants.
344
339
  await nullBlindIndexesForSubject(crossTenantSubjectRunner, ctx.registry.features, subjectKey);
345
340
 
346
- // Derived search index still holds plaintext (#1610) — purge next to the
341
+ // Derived search index still holds plaintext — purge next to the
347
342
  // blind-index sweep. No adapter → no-op (apps without search).
348
343
  if (ctx.searchAdapter) {
349
344
  await purgeSearchDocumentsForSubject(
@@ -367,8 +362,14 @@ async function sweepDerivedSubjectData(
367
362
  });
368
363
 
369
364
  // File columns hold only the fileRef id, so the key erase never reaches the bytes.
370
- await runStep((crossTenantSubjectRunner) =>
371
- purgeFilesReachingSubject({
365
+ await runStep(async (crossTenantSubjectRunner) => {
366
+ // Inside the step: a failing owner lookup must land in the audit label, not abort the handler.
367
+ const recordTenantId = await owningTenantOfRecordSubject(
368
+ crossTenantSubjectRunner,
369
+ ctx.registry.features,
370
+ rawSubject,
371
+ );
372
+ await purgeFilesReachingSubject({
372
373
  registry: ctx.registry,
373
374
  db: crossTenantSubjectRunner,
374
375
  subject,
@@ -376,8 +377,8 @@ async function sweepDerivedSubjectData(
376
377
  ...(recordTenantId !== undefined && { recordTenantId }),
377
378
  resolveDeleteBytes: resolveFileBytesDeleter(ctx),
378
379
  missingStorage: { mode: "fail" },
379
- }),
380
- );
380
+ });
381
+ });
381
382
 
382
383
  return failureLabels[0];
383
384
  }
@@ -442,7 +443,8 @@ async function appendSubjectForgotten(
442
443
  {
443
444
  registry: ctx.registry,
444
445
  db: outsideRunner,
445
- // MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw bypasses TenantDb's scoping (fw#2452).
446
+ // MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw bypasses TenantDb's
447
+ // scoping.
446
448
  tenantId: event.user.tenantId,
447
449
  userId: String(event.user.id),
448
450
  callSiteLabel: "forget-subject audit",
@@ -466,7 +468,7 @@ async function appendSubjectForgotten(
466
468
  // The automated Art.-17 path (user-data-rights forget-cleanup) calls
467
469
  // kms.eraseKey directly inside its per-user sub-tx; this command is the
468
470
  // standalone trigger for cases outside that pipeline (authority requests,
469
- // tenant-destroy in Sprint 5, operator recovery).
471
+ // tenant-destroy, operator recovery).
470
472
  export const forgetSubjectWrite = defineWriteHandler({
471
473
  name: "forget-subject",
472
474
  schema: forgetSubjectSchema,
@@ -558,7 +560,7 @@ export const forgetSubjectWrite = defineWriteHandler({
558
560
  // callable. Mirror of the automated Art.-17 path (userDeleteHook:
559
561
  // status=Deleted; apiTokenDeleteHook: revoke):
560
562
  // - user.updated as lifecycle event (updateUserLifecycle), so a
561
- // read_users rebuild doesn't wipe the flip (#494)
563
+ // read_users rebuild doesn't wipe the flip
562
564
  // - sessions don't need active revocation — session-callbacks
563
565
  // re-validate user.status on every request (isPrincipalBlocked
564
566
  // blocks Deleted).
@@ -1,28 +1,27 @@
1
1
  import { v5 as uuidv5 } from "uuid";
2
2
 
3
- // Fixed UUID-namespace für custom-field-definition aggregate-id-Ableitung.
4
- // Generiert einmalig (2026-05-22), in Stein gemeißelt: ein Wechsel würde
5
- // jeden existing fieldDefinition-Stream re-keyen → kaputter event-replay,
6
- // kaputte definition-history. Drift-Pin in __tests__/drift.test.ts.
3
+ // Fixed UUID namespace for deriving custom-field definition aggregate IDs.
4
+ // Generated once; changing it would re-key every existing fieldDefinition stream,
5
+ // breaking event replay and definition history. Drift is pinned in
6
+ // __tests__/drift.test.ts.
7
7
  const FIELD_DEFINITION_NAMESPACE = "f1d3b2c7-4e5a-4b9c-8d1f-2a3b4c5d6e7f";
8
8
 
9
9
  /**
10
- * Deterministic aggregate-id für ein fieldDefinition-Aggregate aus dem
11
- * Tripel (tenantId, entityName, fieldKey). Pro (Tenant|System, Entity,
12
- * FieldKey) existiert genau ein Aggregate.
10
+ * Deterministic aggregate ID for a fieldDefinition aggregate from the tuple
11
+ * (tenantId, entityName, fieldKey). Exactly one aggregate exists per
12
+ * (Tenant|System, Entity, FieldKey).
13
13
  *
14
- * **Scope-Semantik:**
15
- * - System-Scope: `tenantId = SYSTEM_TENANT_ID` → die fieldDefinition
16
- * gilt für alle Tenants (vendor-defined).
17
- * - Tenant-Scope: `tenantId = <tenant-uuid>` → pro Tenant eigene
14
+ * **Scope semantics:**
15
+ * - System scope: `tenantId = SYSTEM_TENANT_ID` → the fieldDefinition applies
16
+ * to all tenants (vendor-defined).
17
+ * - Tenant scope: `tenantId = <tenant-uuid>` → each tenant has its own
18
18
  * fieldDefinition.
19
19
  *
20
- * **Conflict-Rule** (durchgesetzt im write-handler, NICHT via DB-constraint):
21
- * Pro (entityName, fieldKey) darf nur EINE Definition existieren — entweder
22
- * system oder tenant, nicht beide. Wenn system `customer.internalNumber`
23
- * definiert, kann Tenant kein eigenes `customer.internalNumber` mehr
24
- * definieren (422 `fieldKey_conflict`). Verhindert Resolution-Ambiguität
25
- * beim Read.
20
+ * **Conflict rule** (enforced in the write handler, NOT via a DB constraint):
21
+ * Only ONE definition may exist per (entityName, fieldKey)—system or tenant,
22
+ * but not both. If system defines `customer.internalNumber`, a tenant cannot
23
+ * define its own `customer.internalNumber` (422 `fieldKey_conflict`). This
24
+ * prevents ambiguity when resolving the field during reads.
26
25
  */
27
26
  // @wrapper-known uuid-domain
28
27
  export function fieldDefinitionAggregateId(
@@ -5,35 +5,36 @@ import {
5
5
  createTextField,
6
6
  } from "@cosmicdrift/kumiko-framework/engine";
7
7
 
8
- // fieldDefinition — Tenant- oder System-scoped Custom-Field-Definition.
8
+ // fieldDefinition — Tenant- or system-scoped custom-field definition.
9
9
  //
10
- // **Tenant-Scope:** `tenantId`-Base-Column wird vom Framework automatisch
11
- // gesetzt. Bei system-scope-Definitionen ist `tenantId = SYSTEM_TENANT_ID`;
12
- // bei tenant-scope der current-tenant. Beide leben in derselben Tabelle,
13
- // Scope ergibt sich aus dem tenantId-Wert (no separate `scope`-column).
10
+ // **Tenant scope:** The `tenantId` base column is set automatically by the
11
+ // framework. For system-scope definitions, `tenantId = SYSTEM_TENANT_ID`;
12
+ // for tenant-scope definitions, it is the current tenant. Both use the same
13
+ // table; the scope is determined by the tenantId value (no separate `scope`
14
+ // column).
14
15
  //
15
- // **Conflict-Rule:** pro (entityName, fieldKey) darf nur eine Definition
16
- // existieren — entweder system oder tenant, nicht beide. Resolution beim
17
- // Read = `WHERE tenantId IN (SYSTEM_TENANT_ID, <current-tenant>)`.
18
- // Conflict-Check ist write-handler-side, NICHT DB-constraint (DB hat
19
- // natürliche UNIQUE auf (tenantId, entityName, fieldKey) durch Aggregate-
20
- // ID-Konstruktion).
16
+ // **Conflict rule:** only one definition may exist per (entityName, fieldKey)
17
+ // — either system or tenant, not both. Resolution on read = `WHERE tenantId IN
18
+ // (SYSTEM_TENANT_ID, <current-tenant>)`. The conflict check is performed by
19
+ // the write handler, NOT enforced by a DB constraint (the DB has a natural
20
+ // UNIQUE constraint on (tenantId, entityName, fieldKey) through aggregate-ID
21
+ // construction).
21
22
  //
22
- // **Spec-Drift**: Spec Z.40-54 hat eine separate `custom_field_value`-
23
- // Tabelle. Plan-Doc v2 hat das durch jsonb-on-host-entity ersetzt
24
- // (D2-pur-Storage). Hier definieren wir NUR die definition-Entity; values
25
- // landen in `read_<entity>.customFields` jsonb via MSP (B2).
23
+ // **Spec drift**: Spec Z.40-54 defines a separate `custom_field_value` table.
24
+ // Plan-Doc v2 replaced it with jsonb on the host entity (pure jsonb storage).
25
+ // This defines ONLY the definition entity; values land in
26
+ // `read_<entity>.customFields` jsonb via MSP.
26
27
  //
27
- // **Was hier NICHT als Stammfeld-Spalte landet**:
28
- // - `defaultValue`, `options`, `fieldAccess`, `label` — alles in
29
- // `serializedField` jsonb gepackt (Builder-Reuse: dehydrierter
30
- // r.field.X()-Output). Spec Z.18-38 listet sie als separate Spalten,
31
- // aber Builder-Reuse macht das redundant — der serialized Builder
32
- // enthält alle diese Aspekte type-safe.
33
- // - `version` (optimistic-lock) — ES-redundant, wir nutzen aggregate-
34
- // stream-version (Sprint E-Pattern).
35
- // - `createdAt/updatedAt/createdBy/updatedBy` — automatic via base-
36
- // columns + events.
28
+ // **What is NOT stored as a base-field column here**:
29
+ // - `defaultValue`, `options`, `fieldAccess`, `label` — all packed into
30
+ // `serializedField` jsonb (builder reuse: dehydrated
31
+ // r.field.X()-output). Spec Z.18-38 lists them as separate columns, but
32
+ // builder reuse makes that redundant — the serialized builder contains all
33
+ // these aspects in a type-safe form.
34
+ // - `version` (optimistic lock) — redundant with event sourcing; we use the
35
+ // aggregate stream version.
36
+ // - `createdAt/updatedAt/createdBy/updatedBy` — automatic through base
37
+ // columns and events.
37
38
  export const fieldDefinitionEntity = createEntity({
38
39
  table: "read_custom_field_definitions",
39
40
  description:
@@ -47,20 +48,21 @@ export const fieldDefinitionEntity = createEntity({
47
48
  // NB: `retention.strategy` below is the data-retention purge policy, a
48
49
  // SEPARATE knob from this executor flag — it does not drive executor.delete.
49
50
  softDelete: true,
50
- // B1.5 retention-policy — fieldDefinitions sind tenant-Schema-Metadaten,
51
- // keine PII-Daten. Lange Retention für Audit (Compliance kann "wann hat
52
- // Tenant das Feld definiert / geändert / gelöscht" fragen).
51
+ // Retention policy — field definitions are tenant-schema metadata, not PII.
52
+ // Long retention supports audits (compliance can ask when a tenant defined,
53
+ // changed, or deleted the field).
53
54
  //
54
- // 10-Jahre keepFor ist konservativer Default; per-Tenant kann via
55
- // tenantRetentionOverride für eigene Edge-Cases gesetzt werden
56
- // (z.B. shorter für test-tenants).
55
+ // The 10-year keepFor is a conservative default; tenants can override it
56
+ // through tenantRetentionOverride for their own edge cases
57
+ // (e.g. shorter retention for test tenants).
57
58
  retention: {
58
59
  keepFor: "10y",
59
60
  strategy: "softDelete",
60
61
  },
61
62
  fields: {
62
- // Ziel-Entity-Name, für die dieses Field definiert wird (z.B. "property",
63
- // "customer"). Max 64 char passt zu Kumiko's entity-name-Convention.
63
+ // The entity name for which this field is defined (e.g. "property",
64
+ // "customer"). The 64-character maximum follows Kumiko's entity-name
65
+ // convention.
64
66
  entityName: createTextField({
65
67
  required: true,
66
68
  maxLength: 64,
@@ -68,8 +70,8 @@ export const fieldDefinitionEntity = createEntity({
68
70
  reason: "technical_reference",
69
71
  }),
70
72
 
71
- // Field-Key (z.B. "internalNumber", "vipFlag") — kebab-case oder camelCase
72
- // erlaubt; UI-rendering nutzt label statt fieldKey.
73
+ // Field key (e.g. "internalNumber", "vipFlag") — kebab-case and camelCase
74
+ // are allowed; UI rendering uses label instead of fieldKey.
73
75
  fieldKey: createTextField({
74
76
  required: true,
75
77
  maxLength: 64,
@@ -77,8 +79,8 @@ export const fieldDefinitionEntity = createEntity({
77
79
  reason: "technical_reference",
78
80
  }),
79
81
 
80
- // Field-Type aus dem SUPPORTED_FIELD_TYPES-Set. Validiert via Zod im
81
- // write-handler.
82
+ // Field type from the SUPPORTED_FIELD_TYPES set. Validated with Zod in the
83
+ // write handler.
82
84
  type: createTextField({
83
85
  required: true,
84
86
  maxLength: 16,
@@ -86,22 +88,22 @@ export const fieldDefinitionEntity = createEntity({
86
88
  reason: "technical_reference",
87
89
  }),
88
90
 
89
- // Required-Flag — wird beim Entity-Write gegen den value gecheckt
90
- // (Stammfeld-identische Semantik, Spec-Promise Z.4).
91
+ // Required flag — checked against the value during entity writes
92
+ // (the same semantics as a base field).
91
93
  required: createBooleanField({ required: true }),
92
94
 
93
- // Searchable-Flag — wenn true, contribuiert das Field zum Search-Doc
94
- // via F3 search-payload-extension.
95
+ // Searchable flag — when true, the field contributes to the search document
96
+ // through the search-payload extension.
95
97
  searchable: createBooleanField({ required: true }),
96
98
 
97
- // UI-Display-Order. Tenant kann seine Felder via UI sortieren.
99
+ // UI display order, allowing tenants to sort their fields in the UI.
98
100
  displayOrder: createNumberField({ required: true, integer: true }),
99
101
 
100
- // Builder-Reuse: serialisierter r.field.X(opts)-Output als jsonb.
101
- // Beinhaltet type-options (enum-values, money-currency, embedded-schema),
102
- // defaultValue, fieldAccess, i18n-labels. Beim Write-Validation
103
- // dehydriert der handler dies zurück zu einer r.field.X()-Instanz und
104
- // nutzt deren .schema für value-Validation.
102
+ // Builder reuse: serialized r.field.X(opts) output stored as jsonb.
103
+ // It includes type options (enum values, money currency, embedded schema),
104
+ // defaultValue, fieldAccess, and i18n labels. During write validation, the
105
+ // handler dehydrates this back into an r.field.X() instance and uses its
106
+ // .schema for value validation.
105
107
  serializedField: createTextField({
106
108
  required: true,
107
109
  maxLength: 65536,
@@ -1,17 +1,16 @@
1
1
  import * as z from "zod";
2
2
 
3
- // Domain-Events für custom-field-VALUES. customField.set + .cleared leben
4
- // auf der host-aggregate stream (Plan-Doc v2 ES-Option-B: customField-Events
5
- // auf demselben Stream wie die host-entity's eigene Events).
3
+ // Domain events for custom-field values. customField.set and .cleared live
4
+ // on the host aggregate stream, alongside the host entity's own events.
6
5
  //
7
- // Aggregate-Type im Event ist der host-entity-name (z.B. "property"),
8
- // aggregate-id ist die host-entity-row-id (z.B. property-uuid). So konsumieren
9
- // die customFields-MSPs nur die Events ihrer wired-entities (filtered via
10
- // aggregate-type-match an der jeweiligen consumer-side-MSP-Registration).
6
+ // The event's aggregate type is the host entity name (for example, "property"),
7
+ // and its aggregate ID is the host entity row ID (for example, property-uuid).
8
+ // This ensures customFields-MSPs consume only events for their wired entities,
9
+ // filtered by aggregate-type match in each consumer-side-MSP registration.
11
10
 
12
11
  export const customFieldSetSchema = z.object({
13
12
  fieldKey: z.string().min(1).max(64),
14
- // Every set carries its value (custom fields hold no PII, #972) — replay
13
+ // Every set carries its value (custom fields hold no PII) — replay
15
14
  // reproduces the projection fully. Stays optional at the type layer only
16
15
  // because z.unknown() is inherently optional; the apply side treats
17
16
  // `value === undefined` as an anomaly and warns.