@cosmicdrift/kumiko-bundled-features 0.385.0 → 0.387.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/LICENSE +21 -57
  2. package/dist/agent-tools/tool-catalog.js +1 -1
  3. package/dist/agent-tools/tool-dispatch.js +0 -2
  4. package/dist/audit/screens.js +1 -1
  5. package/dist/auth-email-password/feature.js +1 -1
  6. package/dist/auth-email-password/handlers/change-password.write.js +3 -3
  7. package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
  8. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
  9. package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
  10. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  11. package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
  12. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  13. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
  14. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  15. package/dist/auth-email-password/handlers/login.write.js +1 -1
  16. package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
  17. package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
  18. package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
  19. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  20. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
  21. package/dist/auth-email-password/index.js +5 -5
  22. package/dist/auth-email-password/lockout-store.js +1 -1
  23. package/dist/auth-email-password/seeding.d.ts +42 -45
  24. package/dist/auth-email-password/seeding.js +51 -53
  25. package/dist/auth-email-password/signup-token-store.js +8 -8
  26. package/dist/auth-email-password/testing.js +3 -3
  27. package/dist/auth-email-password/web/auth-client.d.ts +2 -2
  28. package/dist/auth-email-password/web/auth-client.js +36 -37
  29. package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
  30. package/dist/auth-email-password/web/auth-gate.js +15 -16
  31. package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
  32. package/dist/auth-email-password/web/client-plugin.js +4 -5
  33. package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
  34. package/dist/auth-email-password/web/constants.js +3 -3
  35. package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
  36. package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
  37. package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
  38. package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
  39. package/dist/auth-email-password/web/index.js +5 -5
  40. package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
  41. package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
  42. package/dist/auth-email-password/web/login-screen.d.ts +1 -1
  43. package/dist/auth-email-password/web/login-screen.js +2 -3
  44. package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
  45. package/dist/auth-email-password/web/reset-password-screen.js +12 -13
  46. package/dist/auth-email-password/web/session.d.ts +10 -9
  47. package/dist/auth-email-password/web/session.js +28 -29
  48. package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
  49. package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
  50. package/dist/auth-email-password/web/signup-screen.js +13 -13
  51. package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
  52. package/dist/auth-email-password/web/tenant-switcher.js +21 -22
  53. package/dist/auth-email-password/web/use-shell-user.js +12 -13
  54. package/dist/auth-email-password/web/user-menu.d.ts +4 -4
  55. package/dist/auth-email-password/web/user-menu.js +12 -13
  56. package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
  57. package/dist/auth-email-password/web/verify-email-screen.js +9 -10
  58. package/dist/auth-foundation/boot-checks.js +4 -4
  59. package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
  60. package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
  61. package/dist/auth-foundation/types.js +2 -2
  62. package/dist/auth-mfa/handlers/disable.write.js +3 -3
  63. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
  64. package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
  65. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  66. package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
  67. package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
  68. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  69. package/dist/auth-mfa/token-secrets.js +1 -1
  70. package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
  71. package/dist/auth-mfa/web/client-plugin.js +1 -1
  72. package/dist/auth-mfa/web/i18n.js +3 -3
  73. package/dist/auth-mfa/web/index.js +4 -4
  74. package/dist/auth-mfa/web/mfa-client.js +17 -16
  75. package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
  76. package/dist/billing-foundation/aggregate-id.d.ts +5 -5
  77. package/dist/billing-foundation/aggregate-id.js +10 -11
  78. package/dist/billing-foundation/entities.js +27 -27
  79. package/dist/billing-foundation/events.js +18 -17
  80. package/dist/billing-foundation/feature.js +42 -43
  81. package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
  82. package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
  83. package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
  84. package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
  85. package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
  86. package/dist/billing-foundation/handlers/process-event.write.js +20 -20
  87. package/dist/billing-foundation/projection.d.ts +15 -11
  88. package/dist/billing-foundation/projection.js +38 -37
  89. package/dist/billing-foundation/subscription-tier-sync.js +3 -3
  90. package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
  91. package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
  92. package/dist/billing-foundation/types.d.ts +40 -41
  93. package/dist/billing-foundation/types.js +20 -20
  94. package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
  95. package/dist/cap-counter/aggregate-id.js +8 -9
  96. package/dist/cap-counter/constants.js +11 -12
  97. package/dist/cap-counter/enforce-cap.d.ts +59 -62
  98. package/dist/cap-counter/enforce-cap.js +47 -48
  99. package/dist/cap-counter/entity.js +29 -29
  100. package/dist/cap-counter/feature.js +34 -35
  101. package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
  102. package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
  103. package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
  104. package/dist/cap-counter/stock-cap-guard.js +1 -1
  105. package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
  106. package/dist/channel-email/smtp-transport.d.ts +18 -17
  107. package/dist/channel-email/smtp-transport.js +24 -21
  108. package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
  109. package/dist/compliance-profiles/feature.js +4 -4
  110. package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
  111. package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
  112. package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
  113. package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
  114. package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
  115. package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
  116. package/dist/compliance-profiles/schema/profile-selection.js +18 -23
  117. package/dist/compliance-profiles/seeding.js +14 -15
  118. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
  119. package/dist/compliance-profiles-ops/index.js +2 -2
  120. package/dist/config/handlers/readiness.query.d.ts +4 -4
  121. package/dist/config/handlers/readiness.query.js +1 -1
  122. package/dist/config/handlers/reencrypt.job.js +4 -5
  123. package/dist/config/handlers/set.write.js +4 -4
  124. package/dist/config/resolver.js +4 -4
  125. package/dist/config/table.js +10 -10
  126. package/dist/config/write-helpers.js +1 -1
  127. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
  128. package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
  129. package/dist/custom-fields/aggregate-id.d.ts +12 -13
  130. package/dist/custom-fields/aggregate-id.js +16 -17
  131. package/dist/custom-fields/entity.js +49 -47
  132. package/dist/custom-fields/events.js +7 -8
  133. package/dist/custom-fields/feature.d.ts +14 -14
  134. package/dist/custom-fields/feature.js +53 -54
  135. package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
  136. package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
  137. package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
  138. package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
  139. package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
  140. package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
  141. package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
  142. package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
  143. package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
  144. package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
  145. package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
  146. package/dist/custom-fields/lib/field-access.js +2 -2
  147. package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
  148. package/dist/custom-fields/lib/quota.js +1 -1
  149. package/dist/custom-fields/lib/value-schema.js +10 -12
  150. package/dist/custom-fields/run-retention.js +3 -3
  151. package/dist/custom-fields/schemas.js +14 -14
  152. package/dist/custom-fields/web/client-plugin.js +2 -5
  153. package/dist/custom-fields/web/constants.js +2 -2
  154. package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
  155. package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
  156. package/dist/custom-fields/wire-for-entity.js +65 -67
  157. package/dist/custom-fields/wire-user-data-rights.js +3 -3
  158. package/dist/data-retention/_internal/parse-override.js +2 -3
  159. package/dist/data-retention/feature.js +11 -18
  160. package/dist/data-retention/handlers/policy-for.query.js +6 -6
  161. package/dist/data-retention/keep-for.d.ts +7 -7
  162. package/dist/data-retention/keep-for.js +15 -15
  163. package/dist/data-retention/override-schema.d.ts +3 -4
  164. package/dist/data-retention/override-schema.js +13 -15
  165. package/dist/data-retention/presets.d.ts +4 -5
  166. package/dist/data-retention/presets.js +18 -23
  167. package/dist/data-retention/resolve-tenant-preset.js +17 -16
  168. package/dist/data-retention/resolver.d.ts +12 -12
  169. package/dist/data-retention/resolver.js +24 -23
  170. package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
  171. package/dist/data-retention/run-retention-cleanup.js +61 -51
  172. package/dist/data-retention/schema/tenant-retention-override.js +13 -11
  173. package/dist/delivery/feature.js +2 -2
  174. package/dist/delivery/handlers/log.query.js +1 -1
  175. package/dist/delivery/tables.js +9 -8
  176. package/dist/delivery/unsubscribe.js +4 -4
  177. package/dist/document-ingest-foundation/entity.js +4 -4
  178. package/dist/document-ingest-foundation/events.js +2 -2
  179. package/dist/document-ingest-foundation/feature.js +2 -2
  180. package/dist/document-ingest-foundation/pages.js +1 -1
  181. package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
  182. package/dist/feature-toggles/compose-tier-resolver.js +1 -1
  183. package/dist/feature-toggles/feature.js +1 -1
  184. package/dist/feature-toggles/global-feature-state-table.js +1 -1
  185. package/dist/feature-toggles/handlers/registered.query.js +5 -5
  186. package/dist/feature-toggles/toggle-sync-signal.js +1 -1
  187. package/dist/feature-toggles/web/constants.js +1 -1
  188. package/dist/file-derivatives/feature.d.ts +1 -1
  189. package/dist/file-derivatives/feature.js +1 -1
  190. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  191. package/dist/file-derivatives/presets.js +1 -1
  192. package/dist/file-foundation/feature.js +6 -6
  193. package/dist/file-provider-inmemory/feature.d.ts +1 -1
  194. package/dist/file-provider-inmemory/feature.js +16 -16
  195. package/dist/file-provider-s3/feature.js +16 -16
  196. package/dist/file-provider-s3/lib/s3-provider.js +6 -6
  197. package/dist/files/feature.js +6 -6
  198. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
  199. package/dist/files-tenant-data/hooks.js +24 -26
  200. package/dist/files-tenant-data/index.js +1 -1
  201. package/dist/folders/feature.d.ts +1 -1
  202. package/dist/folders/web/folder-manager.js +2 -2
  203. package/dist/folders/web/tree.js +5 -5
  204. package/dist/form-draft/db/queries/cleanup.js +1 -1
  205. package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
  206. package/dist/form-draft/entity.js +3 -3
  207. package/dist/form-draft/feature.js +4 -5
  208. package/dist/form-draft/handlers/discard.write.js +1 -1
  209. package/dist/form-draft/release-file-refs.js +6 -6
  210. package/dist/form-draft/schemas.js +3 -3
  211. package/dist/form-draft/web/constants.js +0 -2
  212. package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
  213. package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
  214. package/dist/inbound-mail-foundation/connect-routes.js +4 -3
  215. package/dist/inbound-mail-foundation/constants.d.ts +22 -24
  216. package/dist/inbound-mail-foundation/constants.js +30 -33
  217. package/dist/inbound-mail-foundation/entities.d.ts +12 -12
  218. package/dist/inbound-mail-foundation/entities.js +47 -48
  219. package/dist/inbound-mail-foundation/events.d.ts +4 -3
  220. package/dist/inbound-mail-foundation/events.js +50 -47
  221. package/dist/inbound-mail-foundation/feature.js +39 -39
  222. package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
  223. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
  224. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
  225. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
  226. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
  227. package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
  228. package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
  229. package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
  230. package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
  231. package/dist/inbound-mail-foundation/oauth-state.js +11 -10
  232. package/dist/inbound-mail-foundation/projection.d.ts +4 -4
  233. package/dist/inbound-mail-foundation/projection.js +31 -29
  234. package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
  235. package/dist/inbound-mail-foundation/provider-factory.js +9 -9
  236. package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
  237. package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
  238. package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
  239. package/dist/inbound-mail-foundation/types.d.ts +45 -46
  240. package/dist/inbound-mail-foundation/types.js +21 -21
  241. package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
  242. package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
  243. package/dist/inbound-provider-imap/credential-document.js +13 -13
  244. package/dist/inbound-provider-imap/feature.d.ts +2 -2
  245. package/dist/inbound-provider-imap/feature.js +42 -40
  246. package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
  247. package/dist/inbound-provider-imap/imap-client.js +20 -19
  248. package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
  249. package/dist/inbound-provider-inmemory/feature.js +19 -19
  250. package/dist/jobs/db/queries/retention.js +2 -2
  251. package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
  252. package/dist/jobs/events.js +1 -1
  253. package/dist/jobs/feature.js +5 -6
  254. package/dist/jobs/handlers/detail.query.js +4 -4
  255. package/dist/jobs/handlers/list.query.js +1 -1
  256. package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
  257. package/dist/jobs/handlers/reindex-entity.job.js +1 -1
  258. package/dist/jobs/handlers/retry.write.js +1 -1
  259. package/dist/jobs/job-instant.js +1 -1
  260. package/dist/jobs/job-run-logger.js +10 -11
  261. package/dist/jobs/job-run-table.js +3 -3
  262. package/dist/jobs/screens.js +1 -1
  263. package/dist/jobs/tenant-job-failure-table.js +1 -1
  264. package/dist/jobs/tenant-job-run-table.js +1 -1
  265. package/dist/ledger/entity.js +5 -5
  266. package/dist/ledger/feature.js +3 -3
  267. package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
  268. package/dist/ledger/recurring.js +12 -12
  269. package/dist/ledger/schemas.js +1 -1
  270. package/dist/ledger/web/constants.js +2 -2
  271. package/dist/ledger/web/index.js +7 -7
  272. package/dist/legal-pages/feature.d.ts +4 -4
  273. package/dist/legal-pages/feature.js +25 -26
  274. package/dist/legal-pages/markdown.js +3 -3
  275. package/dist/legal-pages/web/client-plugin.js +23 -24
  276. package/dist/legal-pages/web/index.js +0 -1
  277. package/dist/mail-foundation/feature.d.ts +2 -2
  278. package/dist/mail-foundation/feature.js +24 -25
  279. package/dist/mail-transport-inmemory/feature.d.ts +4 -4
  280. package/dist/mail-transport-inmemory/feature.js +27 -28
  281. package/dist/mail-transport-smtp/feature.js +20 -20
  282. package/dist/managed-pages/branding.js +6 -6
  283. package/dist/managed-pages/feature.d.ts +26 -26
  284. package/dist/managed-pages/feature.js +34 -34
  285. package/dist/managed-pages/handlers/by-slug.query.js +5 -6
  286. package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
  287. package/dist/managed-pages/handlers/set.write.js +5 -7
  288. package/dist/managed-pages/screens/page-screens.js +11 -11
  289. package/dist/managed-pages/seeding.js +8 -8
  290. package/dist/managed-pages/table.js +13 -12
  291. package/dist/managed-pages/web/client-plugin.d.ts +1 -1
  292. package/dist/managed-pages/web/client-plugin.js +5 -5
  293. package/dist/managed-pages/web/i18n.js +1 -1
  294. package/dist/notes-history/entity.js +4 -4
  295. package/dist/notes-history/feature.d.ts +2 -2
  296. package/dist/notes-history-user-data/hooks.js +1 -1
  297. package/dist/page-render/layout.js +9 -9
  298. package/dist/page-render/markdown.js +11 -11
  299. package/dist/page-render/security-headers.js +7 -6
  300. package/dist/personal-access-tokens/feature.js +5 -5
  301. package/dist/personal-access-tokens/roles.js +2 -2
  302. package/dist/readiness/handlers/status.query.js +3 -3
  303. package/dist/renderer-foundation/api.js +12 -13
  304. package/dist/renderer-foundation/constants.js +2 -2
  305. package/dist/renderer-foundation/feature.js +7 -7
  306. package/dist/secrets/feature.js +9 -9
  307. package/dist/secrets/web/constants.js +2 -2
  308. package/dist/seo/feature.js +3 -3
  309. package/dist/sessions/constants.d.ts +1 -1
  310. package/dist/sessions/constants.js +1 -1
  311. package/dist/sessions/feature.js +8 -8
  312. package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
  313. package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
  314. package/dist/sessions/handlers/revoke.write.js +1 -1
  315. package/dist/sessions/schema/user-session.js +4 -4
  316. package/dist/sessions/screens.js +2 -2
  317. package/dist/sessions/session-callbacks.js +2 -2
  318. package/dist/sessions/session-revoked-event.js +2 -2
  319. package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
  320. package/dist/shared/decrypt-stored-pii.js +1 -1
  321. package/dist/shared/encrypt-for-direct-write.js +1 -1
  322. package/dist/shared/map-with-concurrency.js +5 -4
  323. package/dist/shared/parent-visibility.js +2 -2
  324. package/dist/shared/password-hashing.js +1 -1
  325. package/dist/shared/signup-handover.js +1 -2
  326. package/dist/shared/single-use-token-store.js +1 -1
  327. package/dist/subscription-mollie/constants.js +15 -17
  328. package/dist/subscription-mollie/feature.d.ts +17 -18
  329. package/dist/subscription-mollie/feature.js +24 -24
  330. package/dist/subscription-mollie/index.js +3 -3
  331. package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
  332. package/dist/subscription-mollie/plugin-methods.js +15 -14
  333. package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
  334. package/dist/subscription-mollie/verify-webhook.js +27 -27
  335. package/dist/subscription-stripe/constants.js +4 -6
  336. package/dist/subscription-stripe/feature.d.ts +14 -14
  337. package/dist/subscription-stripe/feature.js +35 -34
  338. package/dist/subscription-stripe/index.js +6 -6
  339. package/dist/subscription-stripe/plugin-methods.js +18 -18
  340. package/dist/subscription-stripe/runtime.d.ts +1 -1
  341. package/dist/subscription-stripe/runtime.js +1 -1
  342. package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
  343. package/dist/subscription-stripe/verify-webhook.js +59 -61
  344. package/dist/tags/feature.d.ts +3 -3
  345. package/dist/tags/screens.js +1 -1
  346. package/dist/template-resolver/api.js +10 -10
  347. package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
  348. package/dist/template-resolver/handlers/list.query.js +1 -1
  349. package/dist/template-resolver/handlers/shared.js +2 -2
  350. package/dist/template-resolver/handlers/template-write.js +3 -3
  351. package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
  352. package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
  353. package/dist/template-resolver/seeding.js +4 -4
  354. package/dist/template-resolver/table.js +10 -11
  355. package/dist/template-resolver/web/client-plugin.js +2 -2
  356. package/dist/tenant/feature.js +7 -7
  357. package/dist/tenant/handlers/member-directory.query.js +1 -1
  358. package/dist/tenant/handlers/members.query.js +1 -1
  359. package/dist/tenant/handlers/team-list.query.js +1 -1
  360. package/dist/tenant/handlers/tenant-directory.query.js +1 -1
  361. package/dist/tenant/invitation-table.js +37 -40
  362. package/dist/tenant/membership-table.js +3 -3
  363. package/dist/tenant/schema/tenant.js +7 -9
  364. package/dist/tenant/screens.js +1 -1
  365. package/dist/tenant/seeding.d.ts +6 -5
  366. package/dist/tenant/seeding.js +12 -12
  367. package/dist/tenant/testing.js +5 -6
  368. package/dist/tenant/web/constants.js +2 -2
  369. package/dist/tenant-handover/events.js +5 -7
  370. package/dist/tenant-handover/feature.js +1 -1
  371. package/dist/tenant-handover/grant.js +1 -1
  372. package/dist/tenant-handover/handlers/claim.write.js +1 -1
  373. package/dist/tenant-handover/move-entity-graph.js +8 -9
  374. package/dist/tenant-handover/signup-handover-provider.js +1 -2
  375. package/dist/tenant-handover/transfer-graph.js +4 -5
  376. package/dist/tenant-lifecycle/boot-checks.js +1 -1
  377. package/dist/tenant-lifecycle/feature.js +1 -1
  378. package/dist/tenant-settings/constants.js +1 -1
  379. package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
  380. package/dist/tenant-settings/tenant-defaults.js +9 -2
  381. package/dist/tier-engine/aggregate-id.d.ts +11 -11
  382. package/dist/tier-engine/aggregate-id.js +15 -16
  383. package/dist/tier-engine/compose-app.d.ts +14 -14
  384. package/dist/tier-engine/compose-app.js +1 -1
  385. package/dist/tier-engine/entity.js +18 -19
  386. package/dist/tier-engine/feature.d.ts +19 -17
  387. package/dist/tier-engine/feature.js +68 -69
  388. package/dist/tier-engine/handlers/active-tier.query.js +6 -7
  389. package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
  390. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
  391. package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
  392. package/dist/tier-engine/tier-resolver.js +2 -2
  393. package/dist/tier-engine/trial.js +8 -8
  394. package/dist/tier-engine/web/index.js +4 -4
  395. package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
  396. package/dist/user/handlers/create.write.js +4 -4
  397. package/dist/user/schema/user.d.ts +11 -11
  398. package/dist/user/schema/user.js +45 -44
  399. package/dist/user/seeding.d.ts +15 -15
  400. package/dist/user/seeding.js +28 -28
  401. package/dist/user/testing.js +3 -3
  402. package/dist/user-data-rights/audit-download.d.ts +8 -8
  403. package/dist/user-data-rights/audit-download.js +19 -20
  404. package/dist/user-data-rights/boot-checks.js +1 -1
  405. package/dist/user-data-rights/deletion-token.js +1 -1
  406. package/dist/user-data-rights/feature.d.ts +49 -50
  407. package/dist/user-data-rights/feature.js +54 -53
  408. package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
  409. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
  410. package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
  411. package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
  412. package/dist/user-data-rights/handlers/export-status.query.js +8 -9
  413. package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
  414. package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
  415. package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
  416. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
  417. package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
  418. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
  419. package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
  420. package/dist/user-data-rights/handlers/request-export.write.js +42 -41
  421. package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
  422. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
  423. package/dist/user-data-rights/index.js +8 -10
  424. package/dist/user-data-rights/lib/default-mailers.js +3 -3
  425. package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
  426. package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
  427. package/dist/user-data-rights/run-export-jobs.js +127 -233
  428. package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
  429. package/dist/user-data-rights/run-forget-cleanup.js +63 -82
  430. package/dist/user-data-rights/run-user-export.d.ts +34 -33
  431. package/dist/user-data-rights/run-user-export.js +55 -57
  432. package/dist/user-data-rights/schema/download-attempt.js +11 -11
  433. package/dist/user-data-rights/schema/download-token.js +37 -41
  434. package/dist/user-data-rights/schema/export-job.d.ts +4 -4
  435. package/dist/user-data-rights/schema/export-job.js +65 -67
  436. package/dist/user-data-rights/token-helpers.d.ts +8 -9
  437. package/dist/user-data-rights/token-helpers.js +21 -25
  438. package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
  439. package/dist/user-data-rights/web/client-plugin.js +1 -1
  440. package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
  441. package/dist/user-data-rights/web/constants.js +1 -1
  442. package/dist/user-data-rights/web/index.js +5 -5
  443. package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
  444. package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
  445. package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
  446. package/dist/user-data-rights/zip-path.d.ts +15 -15
  447. package/dist/user-data-rights/zip-path.js +41 -40
  448. package/dist/user-data-rights-defaults/feature.js +15 -15
  449. package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
  450. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
  451. package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
  452. package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
  453. package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
  454. package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
  455. package/dist/user-profile/handlers/change-email.write.js +13 -13
  456. package/dist/user-profile/index.js +3 -3
  457. package/dist/user-profile/web/client-plugin.js +1 -1
  458. package/dist/user-profile/web/constants.js +1 -1
  459. package/dist/user-profile/web/profile-screen.js +1 -1
  460. package/dist/workflow-runner/aggregate-id.d.ts +1 -1
  461. package/dist/workflow-runner/aggregate-id.js +1 -1
  462. package/dist/workflow-runner/event-subscriber.js +4 -5
  463. package/dist/workflow-runner/event-trigger.js +4 -17
  464. package/dist/workflow-runner/feature.js +2 -2
  465. package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
  466. package/dist/workflow-runner/pending-projection.js +6 -7
  467. package/dist/workflow-runner/runner.js +6 -6
  468. package/dist/workflow-runner/tables.js +6 -6
  469. package/dist/workflow-runner/workflow-registry.js +1 -1
  470. package/package.json +10 -10
@@ -1,25 +1,25 @@
1
1
  // kumiko-feature-version: 1
2
2
  //
3
- // mail-transport-inmemory — In-Memory-EmailTransport für die mail-
4
- // foundation Plugin-API. Sammelt Mails in einem per-Tenant-Buffer
5
- // statt sie über einen echten SMTP-Server zu senden. Designed für
6
- // Demos, Sample-Apps und Tests die ohne Mailpit/Mailcrab/echten SMTP
7
- // laufen sollen.
3
+ // mail-transport-inmemory — In-memory email transport for the mail-
4
+ // foundation plugin API. Collects emails in a per-tenant buffer
5
+ // instead of sending them through a real SMTP server. Designed for
6
+ // demos, sample apps, and tests that should run without Mailpit,
7
+ // Mailcrab, or real SMTP.
8
8
  //
9
- // **Was diese Feature liefert:**
10
- // 1. Plugin-Registration via `r.useExtension("mailTransport",
11
- // "inmemory", { build })`. Tenants setzen
12
- // "mail-foundation:config:provider" auf "inmemory" und kriegen
13
- // die buffered-Variante.
14
- // 2. **Pro-Tenant Inbox.** Jeder Tenant hat einen eigenen
15
- // Mail-Buffer (Map<tenantId, EmailMessage[]>). Demo-Apps können
16
- // die Inbox via `getInbox(tenantId)` lesen + UI rendern.
9
+ // **What this feature provides:**
10
+ // 1. Plugin registration via `r.useExtension("mailTransport",
11
+ // "inmemory", { build })`. Tenants set
12
+ // "mail-foundation:config:provider" to "inmemory" and receive
13
+ // the buffered variant.
14
+ // 2. **Per-tenant inbox.** Each tenant has its own mail buffer
15
+ // (Map<tenantId, EmailMessage[]>). Demo apps can read the inbox
16
+ // via `getInbox(tenantId)` and render a UI.
17
17
  //
18
- // **Pattern-Vorbild:** mirrors mail-transport-smtp.
18
+ // **Pattern reference:** mirrors mail-transport-smtp.
19
19
  //
20
- // **NICHT für Production.** Buffer ist im Process-Memory, geht beim
21
- // Restart verloren. Cap-Counter / Audit-Trail bleiben trotzdem korrekt
22
- // — die hängen am event-store, nicht am Transport.
20
+ // **NOT for production.** The buffer is in process memory and is lost
21
+ // on restart. Cap counters and the audit trail remain correct because
22
+ // they are tied to the event store, not the transport.
23
23
  import { createInMemoryTransport } from "@cosmicdrift/kumiko-bundled-features/channel-email";
24
24
  import { MAIL_TRANSPORT_EXTENSION, } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
25
25
  import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
@@ -28,9 +28,9 @@ const FEATURE_NAME = "mail-transport-inmemory";
28
28
  // Per-tenant in-memory buffer
29
29
  // =============================================================================
30
30
  //
31
- // Module-level Map weil der Plugin-build-call pro Send einen neuen
32
- // Transport-Wrapper baut, aber wir wollen dass alle Wrapper für
33
- // denselben Tenant auf denselben Buffer zeigen. Map<tenantId,
31
+ // The module-level Map is needed because the plugin build call creates
32
+ // a new transport wrapper for each send, while all wrappers for the
33
+ // same tenant must point to the same buffer. Map<tenantId,
34
34
  // InMemoryTransport>.
35
35
  const transportsByTenant = new Map();
36
36
  function getOrCreateTransportForTenant(tenantId) {
@@ -42,15 +42,15 @@ function getOrCreateTransportForTenant(tenantId) {
42
42
  return transport;
43
43
  }
44
44
  /**
45
- * Demo/Test-Helper: lies die "versendeten" Mails eines Tenants. Im
46
- * Sample-App rendert ein query-Handler darauf die Inbox-UI.
45
+ * Demo/test helper: reads the emails "sent" for a tenant. A query
46
+ * handler in the sample app uses this to render the inbox UI.
47
47
  */
48
48
  export function getInbox(tenantId) {
49
49
  return transportsByTenant.get(tenantId)?.sent ?? [];
50
50
  }
51
51
  /**
52
- * Demo/Test-Helper: clear einen Tenant-Buffer (z.B. zwischen Test-
53
- * Szenarien).
52
+ * Demo/test helper: clears a tenant's buffer, for example between
53
+ * test scenarios.
54
54
  */
55
55
  export function clearInbox(tenantId) {
56
56
  const t = transportsByTenant.get(tenantId);
@@ -63,10 +63,9 @@ export function clearInbox(tenantId) {
63
63
  export function createMailTransportInMemoryFeature() {
64
64
  return defineFeature(FEATURE_NAME, (r) => {
65
65
  r.describe('Registers an in-process `"inmemory"` provider for `mail-foundation` that buffers sent mails per tenant instead of contacting an SMTP server. Use `getInbox(tenantId)` and `clearInbox(tenantId)` in demo apps and tests; not for production (buffer is process-memory, lost on restart).');
66
- // Kein requires auf "config" oder "secrets" — der
67
- // In-Memory-Transport hat keine Config (nichts zu konfigurieren) und
68
- // kein Secret. Der einzige hard-require ist mail-foundation, das den
69
- // extension-point "mailTransport" definiert.
66
+ // No `config` or `secrets` requirement: the in-memory transport has
67
+ // no configuration and no secret. The only hard requirement is
68
+ // mail-foundation, which defines the "mailTransport" extension point.
70
69
  r.requires({ features: ["mail-foundation"] });
71
70
  const plugin = {
72
71
  // Solon and studio mount it next to smtp in production; offering it there would
@@ -1,29 +1,29 @@
1
1
  // kumiko-feature-version: 1
2
2
  //
3
- // mail-transport-smtp — concrete SMTP-implementation for the
4
- // mail-foundation plugin-API.
3
+ // mail-transport-smtp — concrete SMTP implementation for the
4
+ // mail-foundation plugin API.
5
5
  //
6
- // **Was diese Feature liefert:**
7
- // 1. Provider-spezifische Tenant-Config (host/port/secure/from/authUser)
8
- // und Secret (smtp.password). Self-contained — mail-foundation kennt
9
- // diese Schlüssel nicht; wenn ein App-Owner zwischen SMTP und Brevo-
10
- // API wechseln will, hat er pro-Plugin eigenständige Config-Sets.
11
- // 2. **Plugin-Registration** via `r.useExtension("mailTransport",
12
- // "smtp", { build })`. Beim Boot kennt mail-foundation's
13
- // Factory-Lookup damit den name "smtp" ↔ build-Funktion.
14
- // 3. `build(ctx, tenantId)` liest die config-keys + secret und ruft
15
- // `createSmtpTransport()` aus channel-email auf. Das ist der
16
- // EINZIGE Cross-Feature-Import dieses Plugins — bewusst lokal
17
- // gehalten, mail-foundation bleibt provider-frei.
6
+ // **What this feature provides:**
7
+ // 1. Provider-specific tenant config (host/port/secure/from/authUser)
8
+ // and secret (smtp.password). Self-contained — mail-foundation does not
9
+ // know these keys; when an app owner switches between SMTP and the Brevo
10
+ // API, each plugin has its own independent config sets.
11
+ // 2. **Plugin registration** via `r.useExtension("mailTransport",
12
+ // "smtp", { build })`. At boot, mail-foundation's factory lookup maps
13
+ // the name "smtp" to the build function.
14
+ // 3. `build(ctx, tenantId)` reads the config keys and secret, then calls
15
+ // `createSmtpTransport()` from channel-email. This is the plugin's
16
+ // ONLY cross-feature import, deliberately kept local so
17
+ // mail-foundation remains provider-independent.
18
18
  //
19
- // **Pattern-Vorbild:** mirrors `channel-email` registering itself for
20
- // `delivery`. Diese Feature ist analog: registriert sich für
21
- // mail-foundation's "mailTransport"-Extension-Point.
19
+ // **Pattern reference:** mirrors `channel-email` registering itself for
20
+ // `delivery`. This feature is analogous: it registers for
21
+ // mail-foundation's "mailTransport" extension point.
22
22
  //
23
- // **Boot-Dependencies:**
23
+ // **Boot dependencies:**
24
24
  // - `mail-foundation` — extension-point owner
25
- // - `config` — für die Tenant-Config-Keys
26
- // - `secrets` — für das verschlüsselte SMTP-Password
25
+ // - `config` — for the tenant config keys
26
+ // - `secrets` — for the encrypted SMTP password
27
27
  import { createSmtpTransport, } from "@cosmicdrift/kumiko-bundled-features/channel-email";
28
28
  import { BlockedHostError, HostResolutionError, mailAllowedPrivateHostsEnvSchema, readAllowedPrivateMailHostsFromEnv, requireDefined, requireNonEmpty, requireSecretSet, resolveMailConnectTarget, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
29
29
  import { MAIL_TRANSPORT_EXTENSION, } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
@@ -14,13 +14,13 @@ import { EMPTY_BRANDING } from "../page-render/index.js";
14
14
  // `write: access.withSystem(access.admin)` — tenant admins self-service via
15
15
  // configEdit AND the system actor (ctx.systemWriteAs) may provision/migrate
16
16
  // these keys. The scope default (`access.admin`, admin-only) has no system
17
- // path, so a continuity migration could not set them (issue #396). Adding
18
- // SYSTEM_ROLE keeps the keys human-writable (checkWriteAccess collapses to
17
+ // path, so a continuity migration could not set them. Adding SYSTEM_ROLE
18
+ // keeps the keys human-writable (checkWriteAccess collapses to
19
19
  // system-only only when system is the SOLE writer), so self-service survives.
20
20
  //
21
- // CONTINUITY (Phase 5 — Prod trap): these keys land under
21
+ // CONTINUITY (Prod trap): these keys land under
22
22
  // `managed-pages:config:branding-*`, NOT the live `publicstatus:config:
23
- // branding-*`. The publicstatus consumer (Phase 5) MUST migrate the existing
23
+ // branding-*`. The publicstatus consumer MUST migrate the existing
24
24
  // read_config_values rows to the new QNs per tenant BEFORE switching the read
25
25
  // path, or every tenant resets to defaults on deploy. The migration is
26
26
  // deliberately NOT built here — the source QNs belong to the consumer app.
@@ -30,7 +30,7 @@ import { EMPTY_BRANDING } from "../page-render/index.js";
30
30
  // also renders. text keys carry an explicit length cap too — `validateType`
31
31
  // only checks the JS type, and the configEdit `maxLength` is client-side, so a
32
32
  // direct config:write:set would otherwise be unbounded (the page body is
33
- // likewise capped in Phase 2).
33
+ // likewise capped).
34
34
  const HEX_PATTERN = {
35
35
  regex: "^$|^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
36
36
  };
@@ -56,7 +56,7 @@ export const MANAGED_PAGES_CSS_FEATURE = "managed-pages-css";
56
56
  // site-url`. BRANDING_QN below is the single source those QN strings are read
57
57
  // from (configEdit screen + render read); the integration test pins write-
58
58
  // target == read-source end-to-end.
59
- // Admin self-service + system provisioning (see write-access note above, #396).
59
+ // Admin self-service + system provisioning.
60
60
  const BRANDING_WRITE = access.withSystem(access.admin);
61
61
  export const BRANDING_KEYS = {
62
62
  brandingTitle: createTenantConfig("text", {
@@ -10,36 +10,36 @@ export type ManagedPagesWrapLayout = (opts: {
10
10
  readonly branding: BrandingTokens;
11
11
  }) => string;
12
12
  export type ManagedPagesOptions = {
13
- /** Host → tenantId für anonyme per-Tenant-Auslieferung. NULL → 404 (kein
14
- * Tenant für diesen Host). Apex-/Marketing-Apps geben hier ihre Subdomain-
15
- * /Custom-Domain-Auflösung rein; single-tenant gibt konstant einen
16
- * tenantId (oder SYSTEM_TENANT_ID) zurück. Erforderlich, weil der Apex-
17
- * Host keinen ambient ctx.tenantId hat. */
13
+ /** Host → tenantId for anonymous per-tenant delivery. NULL → 404 (no
14
+ * tenant for this host). Apex/marketing apps provide their subdomain or
15
+ * custom-domain resolution here; single-tenant apps return a constant
16
+ * tenantId (or SYSTEM_TENANT_ID). Required because the apex host has no
17
+ * ambient ctx.tenantId. */
18
18
  readonly resolveApexTenant: (host: string) => Promise<string | null> | string | null;
19
- /** Custom Layout-Wrapper (Branding/Chrome). Default: minimaler
20
- * page-render-Skeleton. Erhält slug + SEO-Meta zur freien Nutzung.
21
- * **`branding` ist RAW, untrusted tenant input.** `title`/`description`
22
- * sind am Write nur längen-gecappt, NICHT HTML-escaped; `customCss` ist
23
- * ungesanitet. Der Wrapper MUSS sie über die Boundary-Helper emittieren
24
- * (alle re-exported von `@cosmicdrift/kumiko-bundled-features/managed-pages`):
25
- * `brandingHeaderHtml(branding)` + `brandingStyleBlock(branding)` (escapen
26
- * Header/Theme) und — mit allowCustomCss — `tenantStyleBlock(branding.
27
- * customCss)` ins `<head>` plus `TENANT_CONTENT_ATTR` am Body-Container. Ein
28
- * Custom-Wrapper der `branding.title` selbst interpoliert ist stored XSS;
29
- * der Default-Wrapper nutzt durchweg die Helper. */
19
+ /** Custom layout wrapper (branding/chrome). Default: a minimal page-render
20
+ * skeleton. Receives slug + SEO meta for free use.
21
+ * **`branding` is RAW, untrusted tenant input.** `title`/`description`
22
+ * are only length-capped on write, NOT HTML-escaped; `customCss` is
23
+ * unsanitized. The wrapper MUST emit them through the boundary helpers
24
+ * (all re-exported from `@cosmicdrift/kumiko-bundled-features/managed-pages`):
25
+ * `brandingHeaderHtml(branding)` + `brandingStyleBlock(branding)` (which
26
+ * escape header/theme) and, with allowCustomCss, `tenantStyleBlock(branding.
27
+ * customCss)` in the `<head>` plus `TENANT_CONTENT_ATTR` on the body
28
+ * container. A custom wrapper that interpolates `branding.title` itself is
29
+ * stored XSS; the default wrapper uses the helpers throughout. */
30
30
  readonly wrapLayout?: ManagedPagesWrapLayout;
31
- /** Basis-Pfad der Page-Routes. Default "/p" → GET /p/:slug. */
31
+ /** Base path for page routes. Default "/p" → GET /p/:slug. */
32
32
  readonly basePath?: string;
33
- /** Default-Sprache wenn `?lang=` fehlt. Default "en". */
33
+ /** Default language when `?lang=` is missing. Default "en". */
34
34
  readonly defaultLang?: string;
35
- /** Aktiviert die per-Tenant Custom-CSS-Capability (raw, untrusted): ein
36
- * `branding-custom-css` Config-Key + ein CSS-Feld im Branding-Editor + die
37
- * Render-Emission als scoped, allowlist-sanitized `<style data-tenant-css>`.
38
- * Default **false** (fail-closed — opt-in für untrusted-Tenant-Input). Auch
39
- * wenn true, wird die Emission zusätzlich per-Tenant über das
40
- * `managed-pages-css`-Toggle (createManagedPagesCssFeature) gegated, sobald
41
- * ein feature-toggles/tier-engine-Runtime verdrahtet ist. Der Render-time-
42
- * Sanitizer (page-render/css-sanitize) ist der Safety-Boundary. */
35
+ /** Enables the per-tenant custom CSS capability (raw, untrusted): a
36
+ * `branding-custom-css` config key + a CSS field in the branding editor +
37
+ * render emission as a scoped, allowlist-sanitized `<style data-tenant-css>`.
38
+ * Default **false** (fail-closed — opt-in for untrusted tenant input). Even
39
+ * when true, emission is additionally gated per tenant by the
40
+ * `managed-pages-css` toggle (createManagedPagesCssFeature) once a
41
+ * feature-toggles/tier-engine runtime is wired. The render-time sanitizer
42
+ * (page-render/css-sanitize) is the safety boundary. */
43
43
  readonly allowCustomCss?: boolean;
44
44
  };
45
45
  export declare function createManagedPagesFeature(opts: ManagedPagesOptions): FeatureDefinition;
@@ -15,9 +15,9 @@ import { pageEntity } from "./table.js";
15
15
  import { MANAGED_PAGES_I18N } from "./web/i18n.js";
16
16
  // 60s-shared-cache saves the origin-revalidate roundtrip; CMS edits are live within 60s.
17
17
  const PUBLIC_PAGE_CACHE = { kind: "revalidate", maxAgeSeconds: 60 };
18
- // QN-Konstante als dokumentierter Public-Contract — der Render-Pfad ruft
19
- // die by-slug-Query via systemQuery in-process (kein Code-Import des
20
- // Handlers, symmetrisch zum legal-pages-Muster).
18
+ // QN constant as a documented public contract — the render path calls
19
+ // the by-slug query in-process via systemQuery (without importing the
20
+ // handler's code, symmetrically with the legal-pages pattern).
21
21
  const BY_SLUG_QN = "managed-pages:query:by-slug";
22
22
  function brandingRevisionSeed(branding) {
23
23
  return JSON.stringify([
@@ -45,28 +45,28 @@ async function readBrandingViaSystemQuery(systemQuery, tenantId) {
45
45
  return EMPTY_BRANDING;
46
46
  }
47
47
  }
48
- // managed-pages — vom Tenant editierbare, server-gerenderte Public-Pages.
49
- // Generalisiert das legal-pages-Render-Muster: eine dynamische Slug-Route
50
- // (`GET /p/:slug`), die den Tenant aus dem Host auflöst (resolveApexTenant),
51
- // die published Page lädt, Markdown gehärtet rendert (page-render) und über
52
- // einen optionalen wrapLayout in Chrome legt. Drafts → 404. Per-Tenant-
53
- // Content wird per `Vary: Host` cache-isoliert.
48
+ // managed-pages — tenant-editable, server-rendered public pages.
49
+ // Generalizes the legal-pages rendering pattern: a dynamic slug route
50
+ // (`GET /p/:slug`) that resolves the tenant from the Host (resolveApexTenant),
51
+ // loads the published page, renders hardened Markdown (page-render), and wraps
52
+ // it in chrome through an optional wrapLayout. Drafts → 404. Per-tenant
53
+ // content is cache-isolated through `Vary: Host`.
54
54
  //
55
- // Admin-Authoring: registriert entityList + entityEdit für `page` (TenantAdmin/
56
- // SystemAdmin) + die Convention-CRUD-Handler die der Renderer per Konvention
57
- // dispatcht. Die Screens MÜSSEN hier liegen (Boot-Validator verlangt entity-Ref
58
- // same-feature); Nav/Workspace bleibt App-Sache.
55
+ // Admin authoring: registers entityList + entityEdit for `page` (TenantAdmin/
56
+ // SystemAdmin) and the convention CRUD handlers dispatched by the renderer.
57
+ // The screens MUST live here (the boot validator requires the entity reference
58
+ // in the same feature); navigation/workspace remains the app's responsibility.
59
59
  //
60
- // Voraussetzungen am App-Bootstrap:
61
- // • anonymousAccess so verdrahtet, dass der X-Tenant-Header honoriert wird
62
- // — Multi-Tenant nutzt einen tenantResolver (oder keinen defaultTenantId).
63
- // Ein fixer defaultTenantId lockt Single-Tenant und lehnt den per-Page
64
- // gesetzten X-Tenant mit 400 tenant_mismatch ab.
65
- // • Admin-UI: die App zeigt via `r.nav({ screen: "managed-pages:screen:
66
- // page-list" })` + Workspace-Eintrag auf die hier deklarierten Screens
67
- // (cross-feature Nav→Screen ist global-validiert) und grantet ihren Admins
68
- // TenantAdmin. Ohne Nav bleiben die Screens dormant — kein Leak in
69
- // flat-nav-Apps die managed-pages nur zum Public-Render nutzen.
60
+ // App bootstrap requirements:
61
+ // • anonymousAccess must be wired to honor the X-Tenant header
62
+ // — multi-tenant apps use a tenantResolver (or no defaultTenantId).
63
+ // A fixed defaultTenantId locks the app to single-tenant mode and rejects
64
+ // the per-page X-Tenant with 400 tenant_mismatch.
65
+ // • Admin UI: the app exposes these screens via `r.nav({ screen:
66
+ // "managed-pages:screen:page-list" })` plus a workspace entry
67
+ // (cross-feature Nav→Screen is globally validated) and grants its admins
68
+ // TenantAdmin. Without navigation, the screens remain dormant — no leak in
69
+ // flat-nav apps that use managed-pages only for public rendering.
70
70
  export function createManagedPagesFeature(opts) {
71
71
  const wrapLayout = opts.wrapLayout ??
72
72
  ((o) => wrapInLayout({
@@ -112,8 +112,8 @@ export function createManagedPagesFeature(opts) {
112
112
  path: `${basePath}/:slug`,
113
113
  anonymous: true,
114
114
  handler: async (c, { systemQuery }) => {
115
- // `param("slug")` ist string|undefined, weil `path` ein computed
116
- // Template ist (Hono inferiert `:slug` nur aus String-Literalen).
115
+ // `param("slug")` is string|undefined because `path` is a computed
116
+ // template (Hono infers `:slug` only from string literals).
117
117
  const slug = c.req.param("slug");
118
118
  if (!slug)
119
119
  return c.text("not found", 404);
@@ -124,13 +124,13 @@ export function createManagedPagesFeature(opts) {
124
124
  const tenantId = await opts.resolveApexTenant(host);
125
125
  if (!tenantId)
126
126
  return c.text("not found", 404);
127
- // Page + branding read in parallel, beide über systemQuery in-
128
- // process gegen den host-resolved tenantId erzwungen (kein X-Tenant-
129
- // Header-Trick über app.fetch — der sähe für einen host-basierten
130
- // anonymousAccess-Resolver wie ein Client-Override aus und würde
131
- // von resolverTrust: "authoritative" zurecht abgelehnt; siehe
132
- // systemQuery's Doc in http-route.ts). Branding ist Deko → ein
133
- // Fehlschlag degradiert zum unbranded Default, blockt nie die Page.
127
+ // Page and branding are read in parallel, both forced through systemQuery
128
+ // in-process for the host-resolved tenantId (no X-Tenant header trick
129
+ // through app.fetch — for a host-based anonymousAccess resolver, that
130
+ // would look like a client override and would rightly be rejected by
131
+ // resolverTrust: "authoritative"; see systemQuery's documentation in
132
+ // http-route.ts). Branding is decorative → a failure degrades to the
133
+ // unbranded default and never blocks the page.
134
134
  let pageSettled;
135
135
  let brandingResult;
136
136
  try {
@@ -168,8 +168,8 @@ export function createManagedPagesFeature(opts) {
168
168
  "content-type": "text/html; charset=utf-8",
169
169
  vary: "Host",
170
170
  };
171
- // 304 (Revision unverändert) und HEAD überspringen beide das
172
- // Markdown-Rendern — der Body wird ohnehin verworfen.
171
+ // 304 (unchanged revision) and HEAD both skip Markdown rendering — the body
172
+ // would be discarded anyway.
173
173
  if (etagMatches(c.req.raw.headers.get("if-none-match"), etag) || c.req.method === "HEAD") {
174
174
  return cachedSecurePageResponse(c.req.raw, {
175
175
  body: null,
@@ -2,12 +2,11 @@ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import * as z from "zod";
4
4
  import { pagesTable } from "../table.js";
5
- // Public-Read by (tenantId, slug, lang). Anonymous-capable (Landing-/
6
- // Marketing-Pages). Tenant kommt aus query.user.tenantId — am Render-Pfad
7
- // via X-Tenant = Host-resolved-tenant gesetzt. Liefert NUR published Pages
8
- // mit Body: Drafts + leere Pages sind für anonyme Besucher unsichtbar
9
- // (Route → 404). Admin-Editing nutzt die Entity-List/Edit-Screens, nicht
10
- // diese Query.
5
+ // Public read by (tenantId, slug, lang), including anonymous access for landing and
6
+ // marketing pages. The tenant comes from query.user.tenantId, set on the render path
7
+ // via X-Tenant = Host-resolved-tenant. Returns ONLY published pages with a body:
8
+ // drafts and empty pages are invisible to anonymous visitors (the route returns 404).
9
+ // Admin editing uses the entity list/edit screens instead of this query.
11
10
  export const bySlugQuery = defineQueryHandler({
12
11
  name: "by-slug",
13
12
  schema: z.object({
@@ -5,8 +5,8 @@ import { pagesTable } from "../table.js";
5
5
  export const byTenantPublishedQuery = defineQueryHandler({
6
6
  name: "by-tenant-published",
7
7
  schema: z.object({
8
- /** Optional cross-tenant read — nur für SystemAdmin. Symmetrisch zur
9
- * by-slug.query Override-Logik. */
8
+ /** Optional cross-tenant read — only for SystemAdmin. Matches the override
9
+ * logic in by-slug.query. */
10
10
  tenantIdOverride: z.string().min(1).optional(),
11
11
  }),
12
12
  access: { roles: ["anonymous", "User", "TenantAdmin", "SystemAdmin"] },
@@ -14,12 +14,10 @@ const langSchema = z
14
14
  .max(8)
15
15
  .regex(/^[a-z]{2}(-[a-z]{2})?$/i, "lang must be ISO 639-1 (e.g. de, en, en-us)");
16
16
  const executor = createEventStoreExecutor(pagesTable, pageEntity, { entityName: "page" });
17
- // Upsert einer Page — eine Operation pro (tenantId, slug, lang). Tenant-
18
- // Scope default aus event.user; SystemAdmin kann via `tenantIdOverride`
19
- // für einen anderen Tenant schreiben (typisch SYSTEM_TENANT_ID für app-
20
- // weite Pages). published/description/ogImage werden bei Update preserved
21
- // wenn im Payload weggelassen (undefined) — damit ein Publish-Toggle nicht
22
- // den Body überschreiben muss und umgekehrt.
17
+ // Upserts one page per (tenantId, slug, lang). The tenant scope defaults to event.user;
18
+ // SystemAdmin can write to another tenant via `tenantIdOverride` (typically SYSTEM_TENANT_ID
19
+ // for app-wide pages). On update, omitted published/description/ogImage values are preserved
20
+ // so a publish toggle does not overwrite the body, and vice versa.
23
21
  export const setWrite = defineWriteHandler({
24
22
  name: "set",
25
23
  schema: z.object({
@@ -30,7 +28,7 @@ export const setWrite = defineWriteHandler({
30
28
  description: z.string().max(500).nullable().optional(),
31
29
  ogImage: z.string().max(2000).nullable().optional(),
32
30
  published: z.boolean().optional(),
33
- /** Cross-tenant write — nur SystemAdmin (z.B. SYSTEM_TENANT_ID-Pages). */
31
+ /** Cross-tenant write — only SystemAdmin (for example, SYSTEM_TENANT_ID pages). */
34
32
  tenantIdOverride: z.string().min(1).optional(),
35
33
  }),
36
34
  access: { roles: ["TenantAdmin", "SystemAdmin"] },
@@ -1,11 +1,11 @@
1
- // Admin-Authoring-Screens für die `page`-Entity. Reine Daten (JSON-safe) —
2
- // der generische DataTable-/Form-Renderer mountet sie, kein React-Component
3
- // nötig. Beide MÜSSEN im managed-pages-Feature registriert werden (nicht in
4
- // der App): der Boot-Validator verlangt, dass `entity: "page"` im selben
5
- // Feature deklariert ist wie der Screen. Nav/Workspace bleibt App-Sache
6
- // (placement-spezifisch, `default`-Workspace ist ein App-Singleton) — die
7
- // App zeigt via `r.nav({ screen: "managed-pages:screen:page-list" })` darauf
8
- // (cross-feature Nav→Screen ist gegen den globalen Screen-QN-Set validiert).
1
+ // Admin authoring screens for the `page` entity. These are JSON-safe data only —
2
+ // the generic DataTable/form renderer mounts them, so no React component is
3
+ // needed. Both MUST be registered in the managed-pages feature (not in the
4
+ // app): the boot validator requires `entity: "page"` to be declared in the
5
+ // same feature as the screen. Navigation and workspace placement remain app-
6
+ // specific (`default` workspace is an app singleton) — the app points to this
7
+ // via `r.nav({ screen: "managed-pages:screen:page-list" })`.
8
+ // Cross-feature Nav→Screen is validated against the global screen QN set.
9
9
  const ADMIN_ROLES = ["TenantAdmin", "SystemAdmin"];
10
10
  export const pageListScreen = {
11
11
  id: "page-list",
@@ -64,9 +64,9 @@ export const pageEditScreen = {
64
64
  { field: "title", span: 2 },
65
65
  { field: "description", span: 2 },
66
66
  { field: "ogImage", span: 2 },
67
- // Publish/Unpublish: der `published`-Toggle hier IST der
68
- // Publish-Mechanismus (kein separater One-Click-List-Action —
69
- // rowAction-payload kann keine Konstanten injizieren).
67
+ // Publish/Unpublish: the `published` toggle here IS the publishing
68
+ // mechanism (there is no separate one-click list action —
69
+ // rowAction-payload cannot inject constants).
70
70
  { field: "published", span: 1 },
71
71
  ],
72
72
  },
@@ -1,14 +1,14 @@
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
  import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
5
5
  import { runEventStoreSeed, TestUsers, } from "@cosmicdrift/kumiko-framework/seeding";
6
6
  import { pageEntity, pagesTable } from "./table.js";
7
7
  const executor = createEventStoreExecutor(pagesTable, pageEntity, { entityName: "page" });
8
8
  export async function seedPage(db, opts) {
9
- // Default-user muss user.tenantId === opts.tenantId haben (sonst landet
10
- // der event-store-stream im falschen tenant-bucket → version_conflict
11
- // bei späteren echten writes). TestUsers.systemAdmin ist testTenantId(1).
9
+ // The default user must have user.tenantId === opts.tenantId; otherwise the
10
+ // event-store stream ends up in the wrong tenant bucket → version_conflict
11
+ // on subsequent real writes. TestUsers.systemAdmin is testTenantId(1).
12
12
  const by = opts.by ?? { ...TestUsers.systemAdmin, tenantId: opts.tenantId };
13
13
  const tdb = createTenantDb({ db, tenantId: opts.tenantId, mode: "system" });
14
14
  const existing = await fetchOne(db, pagesTable, {
@@ -36,8 +36,8 @@ export async function seedPage(db, opts) {
36
36
  if (!result.isSuccess) {
37
37
  throw new Error(`seedPage create failed: ${JSON.stringify(result)}`);
38
38
  }
39
- // @cast-boundary db-row: executor.create result.data ist die inserted
40
- // Drizzle-Row (Record<string, unknown>), projected nach RETURNING.
39
+ // @cast-boundary db-row: executor.create result.data is the inserted
40
+ // Drizzle row (Record<string, unknown>), projected from RETURNING.
41
41
  const data = result.data;
42
42
  if (data.id === undefined) {
43
43
  throw new Error("seedPage: executor.create did not return an id");
@@ -1,11 +1,12 @@
1
1
  import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { createBooleanField, createEntity, createTextField, } from "@cosmicdrift/kumiko-framework/engine";
3
- // Page — vom Tenant editierbare, server-gerenderte Public-Page (Landing,
4
- // About, custom). Pro (tenantId, slug, lang) genau eine Row. Body ist
5
- // Markdown (gehärtet server-gerendert über page-render). `published` gated
6
- // die Auslieferung an anonyme Besucher: Drafts → 404. description/ogImage
7
- // für SEO + Social-Preview. SYSTEM_TENANT_ID für app-weite Pages, sonst
8
- // Tenant-eigene Pages (Host → tenantId via resolveApexTenant am Render-Pfad).
3
+ // Page — a tenant-editable, server-rendered public page (landing,
4
+ // about, custom). Exactly one row per (tenantId, slug, lang). The body is
5
+ // Markdown, rendered securely on the server via page-render. `published`
6
+ // gates delivery to anonymous visitors: drafts return 404. description and
7
+ // ogImage support SEO and social previews. SYSTEM_TENANT_ID is used for
8
+ // app-wide pages; otherwise the page belongs to the tenant resolved from the
9
+ // host via resolveApexTenant during rendering.
9
10
  export const pageEntity = createEntity({
10
11
  table: "read_pages",
11
12
  description: "One tenant-editable public web page, unique per slug and language, holding a markdown body plus the title, SEO description and OG image, with a published flag that decides whether anonymous visitors are served it or get a 404.",
@@ -32,12 +33,12 @@ export const pageEntity = createEntity({
32
33
  personal: false,
33
34
  reason: "is_business_data",
34
35
  }),
35
- // Body + description sind vom Tenant-Admin authored Business-Content
36
- // (Markdown), keine User-Generated-PII. `multiline` → der entityEdit-
37
- // Renderer gibt ein <textarea> aus (createLongTextField hat aktuell
38
- // einen Render-Gap: edit.ts/render-field.tsx gaten nur type==="text").
39
- // maxLengths spiegeln die Handler-Schemas (set.write + Convention-CRUD
40
- // leiten ihre zod-Caps aus diesen Field-maxLengths ab).
36
+ // Body and description are tenant-admin-authored business content
37
+ // (Markdown), not user-generated PII. `multiline` makes the entityEdit
38
+ // renderer output a <textarea> (createLongTextField currently has a
39
+ // rendering gap: edit.ts/render-field.tsx only gates on type==="text").
40
+ // maxLengths mirror the handler schemas (set.write and convention CRUD
41
+ // derive their zod caps from these field maxLengths).
41
42
  body: createTextField({
42
43
  multiline: { rows: 16 },
43
44
  maxLength: 100_000,
@@ -1,7 +1,7 @@
1
1
  import { type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
2
2
  import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
3
3
  export type ManagedPagesClientOptions = {
4
- /** Key-wise Overrides über die Default-Bundles (de/en). */
4
+ /** Key-wise overrides of the default bundles (de/en). */
5
5
  readonly translations?: TranslationsByLocale;
6
6
  };
7
7
  export declare function managedPagesClient(options?: ManagedPagesClientOptions): ClientFeatureDefinition;
@@ -1,8 +1,8 @@
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
  import { mergeTranslations } from "@cosmicdrift/kumiko-renderer";
7
7
  import { defaultTranslations } from "./default-translations.js";
8
8
  export function managedPagesClient(options) {
@@ -48,7 +48,7 @@ export const MANAGED_PAGES_I18N = {
48
48
  "managed-pages:confirms.page-delete": {
49
49
  en: "Delete this page?",
50
50
  },
51
- // Nur bei allowCustomCss:true im Screen — unconditional geliefert
51
+ // Only used when allowCustomCss:true in the screen; supplied unconditionally
52
52
  "managed-pages:entity:__config-edit__:field:customCss": { en: "Custom CSS" },
53
53
  "managed-pages:branding.section.custom-css": { en: "Custom CSS" },
54
54
  };