@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
@@ -1,6 +1,6 @@
1
- // Test-/Seed-Helper für managed-pages. Legt eine Page direkt über den
2
- // Event-Store-Executor an — gleicher Pfad wie der echte set-Handler, aber
3
- // ohne Access-Check. Default ifExists="skip".
1
+ // Test/seed helper for managed-pages. Creates a page directly through the
2
+ // event-store executor—the same path as the real set handler, but without an
3
+ // access check. Default ifExists="skip".
4
4
 
5
5
  import {
6
6
  createEventStoreExecutor,
@@ -33,9 +33,9 @@ export type SeedPageOptions = {
33
33
  };
34
34
 
35
35
  export async function seedPage(db: DbConnection, opts: SeedPageOptions): Promise<{ id: string }> {
36
- // Default-user muss user.tenantId === opts.tenantId haben (sonst landet
37
- // der event-store-stream im falschen tenant-bucket → version_conflict
38
- // bei späteren echten writes). TestUsers.systemAdmin ist testTenantId(1).
36
+ // The default user must have user.tenantId === opts.tenantId; otherwise the
37
+ // event-store stream ends up in the wrong tenant bucket → version_conflict
38
+ // on subsequent real writes. TestUsers.systemAdmin is testTenantId(1).
39
39
  const by = opts.by ?? { ...TestUsers.systemAdmin, tenantId: opts.tenantId };
40
40
  const tdb = createTenantDb({ db, tenantId: opts.tenantId, mode: "system" });
41
41
 
@@ -70,8 +70,8 @@ export async function seedPage(db: DbConnection, opts: SeedPageOptions): Promise
70
70
  if (!result.isSuccess) {
71
71
  throw new Error(`seedPage create failed: ${JSON.stringify(result)}`);
72
72
  }
73
- // @cast-boundary db-row: executor.create result.data ist die inserted
74
- // Drizzle-Row (Record<string, unknown>), projected nach RETURNING.
73
+ // @cast-boundary db-row: executor.create result.data is the inserted
74
+ // Drizzle row (Record<string, unknown>), projected from RETURNING.
75
75
  const data = result.data as Partial<PageRow>;
76
76
  if (data.id === undefined) {
77
77
  throw new Error("seedPage: executor.create did not return an id");
@@ -5,12 +5,13 @@ import {
5
5
  createTextField,
6
6
  } from "@cosmicdrift/kumiko-framework/engine";
7
7
 
8
- // Page — vom Tenant editierbare, server-gerenderte Public-Page (Landing,
9
- // About, custom). Pro (tenantId, slug, lang) genau eine Row. Body ist
10
- // Markdown (gehärtet server-gerendert über page-render). `published` gated
11
- // die Auslieferung an anonyme Besucher: Drafts → 404. description/ogImage
12
- // für SEO + Social-Preview. SYSTEM_TENANT_ID für app-weite Pages, sonst
13
- // Tenant-eigene Pages (Host → tenantId via resolveApexTenant am Render-Pfad).
8
+ // Page — a tenant-editable, server-rendered public page (landing,
9
+ // about, custom). Exactly one row per (tenantId, slug, lang). The body is
10
+ // Markdown, rendered securely on the server via page-render. `published`
11
+ // gates delivery to anonymous visitors: drafts return 404. description and
12
+ // ogImage support SEO and social previews. SYSTEM_TENANT_ID is used for
13
+ // app-wide pages; otherwise the page belongs to the tenant resolved from the
14
+ // host via resolveApexTenant during rendering.
14
15
  export const pageEntity = createEntity({
15
16
  table: "read_pages",
16
17
  description:
@@ -38,12 +39,12 @@ export const pageEntity = createEntity({
38
39
  personal: false,
39
40
  reason: "is_business_data",
40
41
  }),
41
- // Body + description sind vom Tenant-Admin authored Business-Content
42
- // (Markdown), keine User-Generated-PII. `multiline` → der entityEdit-
43
- // Renderer gibt ein <textarea> aus (createLongTextField hat aktuell
44
- // einen Render-Gap: edit.ts/render-field.tsx gaten nur type==="text").
45
- // maxLengths spiegeln die Handler-Schemas (set.write + Convention-CRUD
46
- // leiten ihre zod-Caps aus diesen Field-maxLengths ab).
42
+ // Body and description are tenant-admin-authored business content
43
+ // (Markdown), not user-generated PII. `multiline` makes the entityEdit
44
+ // renderer output a <textarea> (createLongTextField currently has a
45
+ // rendering gap: edit.ts/render-field.tsx only gates on type==="text").
46
+ // maxLengths mirror the handler schemas (set.write and convention CRUD
47
+ // derive their zod caps from these field maxLengths).
47
48
  body: createTextField({
48
49
  multiline: { rows: 16 },
49
50
  maxLength: 100_000,
@@ -59,9 +60,9 @@ export const pageEntity = createEntity({
59
60
 
60
61
  export const pagesTable = buildEntityTable("page", pageEntity);
61
62
 
62
- // Concrete Row-Type — single-source für die benannten Werte (statt
63
- // `row["x"] as Y`-Casts in Handlern). entity.fields + Standard-Spalten
64
- // (id, version, tenantId, createdAt, updatedAt, createdBy, updatedBy).
63
+ // Concrete row type — the single source of truth for named values instead
64
+ // of `row["x"] as Y` casts in handlers. Includes entity.fields and standard
65
+ // columns (id, version, tenantId, createdAt, updatedAt, createdBy, updatedBy).
65
66
  export type PageRow = {
66
67
  readonly id: string;
67
68
  readonly version: number;
@@ -1,15 +1,15 @@
1
- // Client-Feature-Factory für managed-pages. Bringt NUR die Übersetzungen mit —
2
- // die Screens (page-list/page-edit/branding-settings) sind schema-driven
3
- // (entityList/entityEdit/configEdit), also keine custom-React-Components zu
4
- // registrieren. Apps mounten es in createKumikoApp({ clientFeatures:
5
- // [managedPagesClient()] }), damit die Admin-Labels übersetzt rendern.
1
+ // Client feature factory for managed-pages. It provides ONLY translations —
2
+ // the screens (page-list/page-edit/branding-settings) are schema-driven
3
+ // (entityList/entityEdit/configEdit), so no custom React components are
4
+ // registered. Apps mount it in createKumikoApp({ clientFeatures:
5
+ // [managedPagesClient()] }) so the admin labels render translated.
6
6
 
7
7
  import { mergeTranslations, type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
8
8
  import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
9
9
  import { defaultTranslations } from "./default-translations.ts";
10
10
 
11
11
  export type ManagedPagesClientOptions = {
12
- /** Key-wise Overrides über die Default-Bundles (de/en). */
12
+ /** Key-wise overrides of the default bundles (de/en). */
13
13
  readonly translations?: TranslationsByLocale;
14
14
  };
15
15
 
@@ -56,7 +56,7 @@ export const MANAGED_PAGES_I18N: Readonly<Record<string, LocalizedString>> = {
56
56
  en: "Delete this page?",
57
57
  },
58
58
 
59
- // Nur bei allowCustomCss:true im Screen — unconditional geliefert
59
+ // Only used when allowCustomCss:true in the screen; supplied unconditionally
60
60
  "managed-pages:entity:__config-edit__:field:customCss": { en: "Custom CSS" },
61
61
  "managed-pages:branding.section.custom-css": { en: "Custom CSS" },
62
62
  };
@@ -15,7 +15,7 @@ import {
15
15
  // Strictly append-only by design: no update/delete write-handler is
16
16
  // registered (see feature.ts). A correction is a new entry, not an edit —
17
17
  // that is the whole point of a note *history* instead of the single
18
- // overwritable textarea this bundle replaces (solon#13).
18
+ // overwritable textarea this bundle replaces.
19
19
  //
20
20
  // `body` is about the HOST entity (entityType/entityId), not the author — the
21
21
  // author is never the data subject of a note's content, so it is deliberately
@@ -24,7 +24,7 @@ import {
24
24
  // employee leaving triggers a forget), garbling unrelated business notes
25
25
  // about customers/projects/etc. — data loss, not privacy.
26
26
  //
27
- // `body` is instead `personal: { of: "id" }` (Row-Subject, fw#2596/#2786):
27
+ // `body` is instead `personal: { of: "id" }` (Row-Subject):
28
28
  // the note's OWN row is its content's subject, so `body` is encrypted under a
29
29
  // per-note key that nothing else shares. That key gets erased only when the
30
30
  // note is reached by a forgotten subject: `note-mention` (below) names the
@@ -34,7 +34,7 @@ import {
34
34
  // shreds `authorName` (`personal: { of: "authorId" }`, the name as stamped at
35
35
  // write time); the two erasures are independent.
36
36
  //
37
- // Known gap (fw#2596, not fixed by this entity): prose that names a third
37
+ // Known gap (not fixed by this entity): prose that names a third
38
38
  // party without a structured @-mention is not tracked — regex/NLP over
39
39
  // free text is unreliable. An operator must erase such a note's own record
40
40
  // subject (`forget-subject` kind "record", entity "note-entry") to cover it.
@@ -86,7 +86,7 @@ export function createNoteEntryEntity(
86
86
  body: createLongTextField({
87
87
  required: true,
88
88
  maxLength: 20_000,
89
- // Row-Subject (fw#2596/#2786): the note itself is the subject, so its
89
+ // Row-Subject: the note itself is the subject, so its
90
90
  // key is erased per-note via `note-mention` lookups, not tied to any
91
91
  // user's own forget.
92
92
  personal: { of: "id" },
@@ -78,8 +78,8 @@ export type NotesHistoryFeatureOptions = {
78
78
  /** Row-level ownership on the note-entry rows themselves — orthogonal to
79
79
  * `access`, which only gates whether a caller may dispatch create/list at
80
80
  * all. `ownership.read` is no longer what keeps a caller from reading notes
81
- * on host entities they can't see: that gate is default-on since fw#2766
82
- * and derives from the entity's `parentRef`. Use `ownership.read` for an
81
+ * on host entities they can't see: that gate is default-on and derives from
82
+ * the entity's `parentRef`. Use `ownership.read` for an
83
83
  * ADDITIONAL row rule on the note row itself (e.g. author-only visibility);
84
84
  * it is AND-ed with the host-visibility gate, never a replacement for it.
85
85
  *
@@ -74,7 +74,7 @@ async function selectNotesReachingSubject(
74
74
  // (entity.ts), so forgetting the AUTHOR already crypto-shreds that field on
75
75
  // its own. `body` is Row-Subject (`personal: { of: "id" }`): its key is per
76
76
  // note, so forgetting a subject only reaches a body when the note structurally
77
- // @-mentions the subject (`note-mention`, fw#2787) or hangs on it as host.
77
+ // @-mentions the subject (`note-mention`) or hangs on it as host.
78
78
  // Free-text mentions are NOT detected — the documented gap in entity.ts.
79
79
  //
80
80
  // Reached bodies are shredded regardless of the host entity's retention strategy:
@@ -51,19 +51,19 @@ const TENANT_CLIP = `${TENANT_SCOPE}{overflow:hidden}`;
51
51
  export function tenantStyleBlock(customCss: string): string {
52
52
  const sanitized = sanitizeTenantCss(customCss, TENANT_SCOPE);
53
53
  if (!sanitized) return "";
54
- // html-ok: sanitizeTenantCss ist die Escaping-Boundary (Allowlist, strippt `<`).
54
+ // html-ok: sanitizeTenantCss is the escaping boundary (allowlist, strips `<`).
55
55
  return `\n<style data-tenant-css>${TENANT_CONTAINMENT}\n${TENANT_CLIP}\n${sanitized}</style>`;
56
56
  }
57
57
 
58
- // Minimaler HTML5-Skeleton mit Inline-CSS — Default-`wrapLayout` für
59
- // server-gerenderte Public-Pages, damit sie auch ohne App-Layout sauber
60
- // aussehen. Apps die ihr eigenes Marketing-Layout (Header/Footer/Theme)
61
- // um den Body legen wollen, übergeben ihre eigene Render-Function.
58
+ // Minimal HTML5 skeleton with inline CSS — the default `wrapLayout` for
59
+ // server-rendered public pages, so they look clean without an app layout.
60
+ // Apps that want to wrap the body in their own marketing layout
61
+ // (header/footer/theme) pass their own render function.
62
62
  //
63
- // Branding (optional): emittiert nach dem Base-`<style>` einen scoped
64
- // `:root`-Override (Accent-Farbe, Layout-Preset → max-width) plus einen
65
- // Logo-/Titel-Header. Alle Branding-Werte sind tenant-supplied + untrusted
66
- // und werden in branding.ts re-validiert/escaped, bevor sie ins Markup gehen.
63
+ // Branding (optional): emits a scoped `:root` override after the base
64
+ // `<style>` (accent color, layout preset → max-width) and a logo/title header.
65
+ // All branding values are tenant-supplied and untrusted; branding.ts
66
+ // revalidates/escapes them before they enter the markup.
67
67
  export function wrapInLayout(opts: {
68
68
  title: string;
69
69
  bodyHtml: string;
@@ -1,15 +1,15 @@
1
1
  import { escapeHtml, isSafeHref } from "@cosmicdrift/kumiko-renderer/headless";
2
2
  import { Marked } from "marked";
3
3
 
4
- // Geteilter, gehärteter Markdown→HTML-Kern für server-gerenderte Public-
5
- // Pages (legal-pages, managed-pages). Annahme: untrusted Tenant-Authoren.
6
- // Raw-HTML-Tokens werden als Text escaped (kein <script>/<img onerror>-
7
- // Passthrough), und link/image-hrefs auf http(s)/mailto/relativ beschränkt
8
- // (kein javascript:/data:). Markdown-Struktur (Headings, Listen, Links,
9
- // Code) bleibt intakt — das neutralisiert die XSS-Vektoren ohne Sanitizer-
10
- // Dependency. Defense-in-Depth ergänzt `securePageHeaders` (`script-src
11
- // 'none'`). GFM aus, breaks aus — strukturierte Pages brauchen keine
12
- // Tables/Strikethrough/Task-Lists.
4
+ // Shared, hardened Markdown→HTML core for server-rendered public
5
+ // pages (legal-pages, managed-pages). Assumption: untrusted tenant authors.
6
+ // Raw HTML tokens are escaped as text (no <script>/<img onerror>-
7
+ // passthrough), and link/image hrefs are restricted to http(s)/mailto/relative
8
+ // (no javascript:/data:). Markdown structure (headings, lists, links,
9
+ // code) remains intact—this neutralizes XSS vectors without a sanitizer
10
+ // dependency. Defense in depth complements `securePageHeaders` (`script-src
11
+ // 'none'`). GFM and breaks are disabled—structured pages do not need
12
+ // tables/strikethrough/task lists.
13
13
  const safeRenderer = new Marked({ gfm: false, breaks: false });
14
14
  safeRenderer.use({
15
15
  walkTokens(token) {
@@ -25,7 +25,7 @@ safeRenderer.use({
25
25
  });
26
26
 
27
27
  export function renderSafeMarkdown(markdown: string): string {
28
- // @cast-boundary third-party-type-gap marked.parse return-type ist `string | Promise<string>`;
29
- // `{ async: false }` garantiert sync (string) — Cast nur API-Vertragsfix.
28
+ // @cast-boundary third-party-type-gap marked.parse return type is `string | Promise<string>`;
29
+ // `{ async: false }` guarantees synchronous output (string)—the cast only fixes the API contract.
30
30
  return safeRenderer.parse(markdown, { async: false }) as string;
31
31
  }
@@ -1,9 +1,10 @@
1
- // Security-Header für server-gerenderte Public-HTML-Pages (legal-pages,
2
- // managed-pages). `script-src 'none'` ist Defense-in-Depth: selbst wenn
3
- // HTML-Injection durchrutscht, läuft kein Script. Bewusst KEIN `default-src`
4
- // → Styles/Images/Fonts bleiben unrestricted (rückwärtskompatibel zu
5
- // Inline-<style>-Layouts wie publicstatus' renderLegalLayout).
6
- // nosniff/SAMEORIGIN/Referrer-Policy sind universell sichere Defaults.
1
+ // Security headers for server-rendered public HTML pages (legal-pages,
2
+ // managed-pages). `script-src 'none'` provides defense in depth: even if
3
+ // HTML injection gets through, no script can run. Deliberately omit
4
+ // `default-src` so styles, images, and fonts remain unrestricted for
5
+ // backward compatibility with inline-<style> layouts such as
6
+ // publicstatus' renderLegalLayout.
7
+ // nosniff/SAMEORIGIN/Referrer-Policy are broadly safe defaults.
7
8
  const PUBLIC_PAGE_SECURITY_HEADERS = {
8
9
  "content-security-policy": "script-src 'none'; object-src 'none'; base-uri 'none'",
9
10
  "x-content-type-options": "nosniff",
@@ -36,7 +36,7 @@ const PAT_REVOKE_TRIGGERING_FIELDS = ["passwordHash"] as const;
36
36
 
37
37
  export type BindPatAutoRevokeOnPasswordChange = (
38
38
  revoker: (userId: string) => Promise<number>,
39
- ) => void;
39
+ ) => () => void;
40
40
 
41
41
  // Reads the late-bind setter off a mounted personal-access-tokens feature's
42
42
  // exports — run{Prod,Dev}App call this once a concrete db is available,
@@ -123,12 +123,12 @@ export function createPersonalAccessTokensFeature(
123
123
  } satisfies AuthProviderPlugin);
124
124
  // Direct-write store like store_user_sessions: create/revoke write it, the
125
125
  // resolver point-reads it. r.entity would make it a rebuildable projection
126
- // whose replay (no token events) would wipe every live token (#498/#494).
126
+ // whose replay (no token events) would wipe every live token.
127
127
  r.storeTable(
128
128
  deriveEntityTableMeta(API_TOKEN_ENTITY_NAME, apiTokenEntity, { source: "unmanaged" }),
129
129
  {
130
130
  reason: "read_side.api_tokens_direct_write",
131
- // create.write encrypts `name` via encryptForDirectWrite (#820).
131
+ // create.write encrypts `name` via encryptForDirectWrite.
132
132
  piiEncryptedOnWrite: true,
133
133
  },
134
134
  );
@@ -145,9 +145,9 @@ export function createPersonalAccessTokensFeature(
145
145
  // Password-change auto-revoke — mirrors sessions' own
146
146
  // autoRevokeOnPasswordChange postSave hook, including WHY it's a
147
147
  // late-bind callback rather than direct ctx.db use: user:write:user:update
148
- // is r.systemScope()'d (the user aggregate is a systemStream, framework
149
- // #497), so a postSave hook on "user" gets a poisoned ctx.db here. The
150
- // concrete revoker is bound once run{Prod,Dev}App has a real db handle.
148
+ // is r.systemScope()'d (the user aggregate is a systemStream), so a postSave hook
149
+ // on "user" gets a poisoned ctx.db here. The concrete revoker is bound once
150
+ // run{Prod,Dev}App has a real db handle.
151
151
  // Explicit option wins; the runtime binding is replaceable so a second boot of the same
152
152
  // feature instance binds its own database.
153
153
  let boundAutoRevoke: ((userId: string) => Promise<number>) | undefined;
@@ -169,6 +169,9 @@ export function createPersonalAccessTokensFeature(
169
169
  });
170
170
  const bindAutoRevokeOnPasswordChange: BindPatAutoRevokeOnPasswordChange = (revoker) => {
171
171
  boundAutoRevoke = revoker;
172
+ return () => {
173
+ if (boundAutoRevoke === revoker) boundAutoRevoke = undefined;
174
+ };
172
175
  };
173
176
 
174
177
  const handlers = {
@@ -12,8 +12,8 @@ import { isPrincipalRowBlocked, type UserStatus, userTable } from "../user/index
12
12
  // time would keep a since-revoked admin role for the token's whole (months-long)
13
13
  // life. Returns null when the user has no membership in that tenant: removed
14
14
  // from the tenant → the PAT stops authenticating there. Also null when the
15
- // user's lifecycle status blocks them (fw security-welle2) — collapsed onto
16
- // the same "no roles" outcome as missing-membership so a blocked user's PAT
15
+ // user's lifecycle status blocks them — collapsed onto the same "no roles"
16
+ // outcome as missing-membership so a blocked user's PAT
17
17
  // gets an identical 401 to an unknown token (no status oracle).
18
18
  export async function resolvePatRoles(
19
19
  db: DbConnection,
@@ -22,9 +22,9 @@ export const statusQuery = defineQueryHandler({
22
22
  // One gate for both halves: required keys/secrets of provider-features
23
23
  // count only while their provider is the selected one (r.extensionSelector).
24
24
  const gate = await buildProviderSelectionGate(ctx, ReadinessQueries.status, query.user, ctx.db);
25
- // skipAccessFilter: das Verdict muss ALLE required Keys zählen — der
26
- // Handler selbst ist TenantAdmin-gated, der Per-Key-Filter wäre hier
27
- // eine ready:true-Lüge für SystemAdmin-gated Keys (277/1).
25
+ // skipAccessFilter: the verdict must count ALL required keys—the
26
+ // Handler itself is TenantAdmin-gated; the per-key filter would falsely
27
+ // report ready:true for SystemAdmin-gated keys.
28
28
  const missingConfig = await collectMissingRequiredConfig(
29
29
  ctx,
30
30
  ReadinessQueries.status,
@@ -1,7 +1,7 @@
1
- // RendererFoundationApi — Cross-Feature-Schnittstelle. Konsumenten
2
- // (delivery, mail-Sender, Solon NKA-PDF-Generator) holen sich pro
3
- // Render-Call den passenden Plugin via `createRendererForTenant`.
4
- // Pattern symmetrisch zu ai-foundation's `createLLMProviderForTenant`.
1
+ // RendererFoundationApi — cross-feature interface. Consumers
2
+ // (delivery, mail sender, Solon NKA PDF generator) retrieve the appropriate
3
+ // plugin for each render call via `createRendererForTenant`.
4
+ // The pattern mirrors ai-foundation's `createLLMProviderForTenant`.
5
5
 
6
6
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
7
7
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
@@ -32,10 +32,9 @@ export type RendererFoundationApi = {
32
32
  }) => RendererPlugin;
33
33
  };
34
34
 
35
- // Plugin-Pool wird zur Boot-Zeit aus Extension-Usages aufgebaut.
36
- // Aus dem Registry kommen alle registrierten Plugins. Foundation-Feature
37
- // baut den Pool via `collectRendererPlugins(registry)` und steckt das
38
- // Result in extraContext.
35
+ // The plugin pool is built at boot time from extension usages.
36
+ // The registry provides all registered plugins. The foundation feature builds
37
+ // the pool via `collectRendererPlugins(registry)` and puts it in extraContext.
39
38
  export function createRendererFoundationApi(
40
39
  plugins: ReadonlyArray<RendererPlugin>,
41
40
  tenantConfigLookup: (tenantId: TenantId) => Record<string, string> | null = () => null,
@@ -50,7 +49,7 @@ export function createRendererFoundationApi(
50
49
  if (tenantPluginName) {
51
50
  const plugin = plugins.find((p) => p.name === tenantPluginName && p.kinds.includes(kind));
52
51
  if (plugin) return plugin;
53
- // Tenant-Config zeigt auf nicht-registriertes Plugin — fällt durch zu Default
52
+ // The tenant configuration points to an unregistered plugin; fall through to the default.
54
53
  }
55
54
 
56
55
  // 2. Default-Plugin
@@ -60,7 +59,7 @@ export function createRendererFoundationApi(
60
59
  if (plugin) return plugin;
61
60
  }
62
61
 
63
- // 3. Erstes Plugin im Pool das das kind bedient
62
+ // 3. First plugin in the pool that serves the kind
64
63
  const first = byKind.get(kind)?.[0];
65
64
  if (first) return first;
66
65
 
@@ -85,14 +84,14 @@ function indexByKind(plugins: ReadonlyArray<RendererPlugin>): Map<RenderKind, Re
85
84
  return map;
86
85
  }
87
86
 
88
- // Single point of truth für "dieser Handler braucht renderer-foundation".
89
- // Pattern symmetrisch zu requireTemplateResolver + requireTextContent.
87
+ // Single source of truth for handlers that require renderer-foundation.
88
+ // The pattern mirrors requireTemplateResolver + requireTextContent.
90
89
  export function requireRendererFoundation(
91
90
  ctx: { readonly rendererFoundation?: RendererFoundationApi } | object,
92
91
  callerName: string,
93
92
  ): RendererFoundationApi {
94
93
  // @cast-boundary engine-bridge — rendererFoundation kommt per extraContext
95
- // aus App-Bootstrap.
94
+ // from the app bootstrap.
96
95
  const api = (ctx as { rendererFoundation?: RendererFoundationApi }).rendererFoundation;
97
96
  if (!api) {
98
97
  throw new InternalError({
@@ -14,8 +14,8 @@ export {
14
14
  type RenderKind,
15
15
  } from "../template-resolver/index.ts";
16
16
 
17
- // Standard-Default-Plugin pro Kind, wenn Tenant keine explizite Config
18
- // gesetzt hat. App-Bootstrap kann das via TenantConfigKey überschreiben.
17
+ // Standard default plugin for each kind when the tenant has not set explicit configuration.
18
+ // App bootstrap can override this through TenantConfigKey.
19
19
  export const DEFAULT_PLUGIN_BY_KIND: Readonly<Record<RenderKindLocal, string>> = {
20
20
  mail: "mail-html",
21
21
  "document-pdf": "puppeteer",
@@ -24,9 +24,9 @@ export function createRendererFoundationFeature() {
24
24
 
25
25
  r.extendsRegistrar(RENDERER_EXTENSION, {
26
26
  onRegister: () => {
27
- // Plugin-Konformitäts-Check könnte hier: shape-validation der
28
- // options (kinds, render-Funktion present). Aktuell kein
29
- // shape-check — Caller's TypeScript-Type-Sicherheit greift.
27
+ // Plugin conformance check could go here: validate the shape of
28
+ // options (kinds, render function present). No shape check currently —
29
+ // the caller's TypeScript type safety applies.
30
30
  },
31
31
  });
32
32
 
@@ -34,11 +34,11 @@ export function createRendererFoundationFeature() {
34
34
  });
35
35
  }
36
36
 
37
- // Plugin-Pool-Aufbau zur Boot-Zeit. App-Bootstrap ruft das nach
38
- // Feature-Registration auf, baut den Pool, gibt ihn via extraContext
39
- // an die Handlers weiter.
37
+ // Build the plugin pool at boot time. App bootstrap calls this after
38
+ // feature registration, builds the pool, and passes it to handlers via
39
+ // extraContext.
40
40
  //
41
- // Symmetrisch zu collectChannels / collectRenderers in delivery-service.
41
+ // Symmetric to collectChannels / collectRenderers in delivery-service.
42
42
  export function collectRendererPlugins(registry: Registry): RendererPlugin[] {
43
43
  const usages = registry.getExtensionUsages(RENDERER_EXTENSION);
44
44
  return usages.map((usage) => {
@@ -10,9 +10,9 @@ import type {
10
10
  } from "../template-resolver/index.ts";
11
11
  import { type ContentFormat, RENDERER_EXTENSION, type RenderKind } from "./constants.ts";
12
12
 
13
- // RenderRequest — Plugins erhalten das. Resource-Mode wählt der Caller
14
- // (renderer-foundation api) je nach kind oder explizit. Plugin selbst
15
- // entscheidet nicht — es bekommt eine schon aufgelöste Form.
13
+ // RenderRequest — plugins receive this. The caller selects resource mode
14
+ // (renderer-foundation API) by kind or explicitly. Plugins do not decide this;
15
+ // they receive an already-resolved form.
16
16
  export type RenderRequest =
17
17
  | { kind: "mail"; payload: MailPayload }
18
18
  | { kind: "document-pdf"; payload: DocumentPdfPayload; options?: PdfOptions }
@@ -157,13 +157,12 @@ export type ImageOptions = {
157
157
  readonly quality?: number;
158
158
  };
159
159
 
160
- // RendererContext — schmale Surface (Kumiko-Style, matcht FileProviderContext
161
- // + ChannelContext). Plugins, die Service-Access brauchen, holen sich
162
- // templateResolver/etc. via direkten Bundle-Import + ctx.db (cross-feature-
163
- // public-API). KEIN extraContext-Pass-Through — Plugin importiert pure-
164
- // Function-Factories statt App-ctx zu casten.
160
+ // RendererContext — a narrow surface (Kumiko-style, matching FileProviderContext
161
+ // + ChannelContext). Plugins that need services obtain templateResolver/etc. via
162
+ // direct bundle imports + ctx.db (cross-feature public API). No extraContext
163
+ // pass-through: plugins import pure function factories instead of casting App-ctx.
165
164
  //
166
- // **Beispiel renderer-mail-html:**
165
+ // **Example renderer-mail-html:**
167
166
  // import { createTemplateResolverApi } from "@cosmicdrift/kumiko-bundled-features/template-resolver";
168
167
  // const tplApi = createTemplateResolverApi(ctx.db, ctx.registry);
169
168
  // const layout = await tplApi.resolveTemplate({ tenantId: ctx.tenantId, slug, kind });
@@ -178,9 +177,9 @@ export type RendererContext = {
178
177
  readonly filesForTenant?: (tenantId: string) => FileContext | undefined;
179
178
  };
180
179
 
181
- // RendererPlugin-Contract — pro Plugin (renderer-mail-html,
182
- // renderer-puppeteer-client). Plugin deklariert welche kinds es bedienen
183
- // kann; Foundation-Resolver wählt basierend auf Tenant-Config + kind.
180
+ // RendererPlugin contract — per plugin (renderer-mail-html,
181
+ // renderer-puppeteer-client). The plugin declares which kinds it can handle;
182
+ // the Foundation resolver selects one based on tenant config + kind.
184
183
  //
185
184
  // Plugin invariants:
186
185
  // - `kinds` has at least one entry, otherwise the plugin is never picked.
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.388.0",
4
+ "type": "fix",
5
+ "title": "renderTablePdf validates the document for direct callers",
6
+ "detail": "renderTablePdf parses the document against pdfTableDocumentSchema and throws RendererError invalid_payload above the row, column and cell caps. Title, subtitle, meta entries, headers, empty text, footer text and page label now have length caps and meta at most 500 entries."
7
+ },
2
8
  {
3
9
  "version": "0.364.0",
4
10
  "type": "fix",
@@ -7,10 +7,13 @@ import type { PdfPageFormat } from "../template-resolver/index.ts";
7
7
  const PDF_TABLE_MAX_ROWS = 10_000;
8
8
  const PDF_TABLE_MAX_COLUMNS = 30;
9
9
  const PDF_TABLE_MAX_CELL_LENGTH = 5_000;
10
+ const PDF_TABLE_MAX_META_ENTRIES = 500;
11
+ const PDF_TABLE_MAX_TEXT_LENGTH = 20_000;
12
+ const PDF_TABLE_MAX_PAGE_LABEL_LENGTH = 100;
10
13
 
11
14
  const pdfTableColumnSchema = z
12
15
  .object({
13
- header: z.string(),
16
+ header: z.string().max(PDF_TABLE_MAX_TEXT_LENGTH),
14
17
  weight: z.number().positive().optional(),
15
18
  align: z.enum(["left", "right"]).optional(),
16
19
  })
@@ -18,10 +21,18 @@ const pdfTableColumnSchema = z
18
21
 
19
22
  export const pdfTableDocumentSchema = z
20
23
  .object({
21
- title: z.string(),
22
- subtitle: z.string().optional(),
24
+ title: z.string().max(PDF_TABLE_MAX_TEXT_LENGTH),
25
+ subtitle: z.string().max(PDF_TABLE_MAX_TEXT_LENGTH).optional(),
23
26
  meta: z
24
- .array(z.object({ label: z.string(), value: z.string() }).readonly())
27
+ .array(
28
+ z
29
+ .object({
30
+ label: z.string().max(PDF_TABLE_MAX_TEXT_LENGTH),
31
+ value: z.string().max(PDF_TABLE_MAX_TEXT_LENGTH),
32
+ })
33
+ .readonly(),
34
+ )
35
+ .max(PDF_TABLE_MAX_META_ENTRIES)
25
36
  .readonly()
26
37
  .optional(),
27
38
  columns: z.array(pdfTableColumnSchema).min(1).max(PDF_TABLE_MAX_COLUMNS).readonly(),
@@ -29,10 +40,10 @@ export const pdfTableDocumentSchema = z
29
40
  .array(z.array(z.string().max(PDF_TABLE_MAX_CELL_LENGTH)).readonly())
30
41
  .max(PDF_TABLE_MAX_ROWS)
31
42
  .readonly(),
32
- emptyText: z.string().optional(),
33
- footerText: z.string().optional(),
43
+ emptyText: z.string().max(PDF_TABLE_MAX_TEXT_LENGTH).optional(),
44
+ footerText: z.string().max(PDF_TABLE_MAX_TEXT_LENGTH).optional(),
34
45
  // Template with `{page}` and `{pages}`; default `"{page} / {pages}"`.
35
- pageLabel: z.string().optional(),
46
+ pageLabel: z.string().max(PDF_TABLE_MAX_PAGE_LABEL_LENGTH).optional(),
36
47
  })
37
48
  .readonly();
38
49
 
@@ -235,12 +246,18 @@ function resolveTableLayout(
235
246
  }
236
247
 
237
248
  export async function renderTablePdf(
238
- doc: PdfTableDocument,
249
+ untrustedDoc: PdfTableDocument,
239
250
  options?: PdfTableOptions,
240
251
  ): Promise<PdfTableResult> {
241
- if (doc.columns.length === 0) {
242
- throw new RendererError("table needs at least one column", "invalid_payload");
252
+ // Direct callers bypass renderTablePdfRequest, so the size caps are enforced here too.
253
+ const parsed = pdfTableDocumentSchema.safeParse(untrustedDoc);
254
+ if (!parsed.success) {
255
+ throw new RendererError(
256
+ `table document is invalid: ${parsed.error.message}`,
257
+ "invalid_payload",
258
+ );
243
259
  }
260
+ const doc = parsed.data;
244
261
  assertRowShape(doc);
245
262
 
246
263
  const pdf = await PDFDocument.create({ updateMetadata: false });
@@ -71,15 +71,15 @@ export const JOIN_REQUEST_TRANSACTION_REASON =
71
71
  "the secret write runs on the request transaction so a failing batch rolls it back together with the config writes";
72
72
 
73
73
  // AppContext carries ctx.secrets via extraContext. requireSecretsContext
74
- // wraps that raw context so every `.get(...)` call auto-includes the
75
- // current user + handler as audit metadata — feature code can't forget
76
- // to log the read (silent bypass of audit was the v1 gap).
74
+ // wraps that raw context so every `.get(...)` call automatically includes
75
+ // the current user and handler as audit metadata, preventing feature code
76
+ // from silently bypassing read auditing.
77
77
  //
78
- // Surface bewusst minimal: HandlerContext-Pfade (Set/Delete-Handler) +
79
- // FileProviderContext-Pfade (S3-Plugin im Worker) liefern dieselben
80
- // zwei Felder, also reicht die schmale ctx-shape — kein voller
81
- // HandlerContext-Import noetig.
82
- // Handler contexts carry the caller as ctx.user, provider contexts set auditUserId (takes precedence).
78
+ // The context shape stays minimal: HandlerContext paths (Set/Delete handlers)
79
+ // and FileProviderContext paths (the S3 plugin in the worker) provide the same
80
+ // two fields, so importing the full HandlerContext is unnecessary.
81
+ // Handler contexts carry the caller as ctx.user; provider contexts set
82
+ // auditUserId, which takes precedence.
83
83
  export function requireSecretsContext(
84
84
  ctx: {
85
85
  readonly secrets?: SecretsContext;
@@ -181,7 +181,7 @@ export function createSecretsFeature(
181
181
  // Backing table: envelope/metadata/last_rotated_at + the (tenant,key)
182
182
  // uniqueIndex are not expressible via the field-DSL (jsonb-without-default,
183
183
  // now()-default), so the physical table is the DDL truth. Without this the
184
- // generated migration omitted those columns → prod-500 (publicstatus#116).
184
+ // generated migration omitted those columns → prod-500.
185
185
  r.entity({ name: "tenant-secret", ...tenantSecretEntity, backingTable: tenantSecretsTable });
186
186
 
187
187
  // Read-audit domain-event. Registered here so ops tools + MSPs can