@cosmicdrift/kumiko-bundled-features 0.362.0 → 0.364.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 (468) hide show
  1. package/dist/admin-shell/feature.d.ts +3 -0
  2. package/dist/admin-shell/feature.js +6 -1
  3. package/dist/agent-tools/agent-manifest.js +2 -1
  4. package/dist/agent-tools/filter-ops.d.ts +1 -1
  5. package/dist/agent-tools/filter-ops.js +1 -3
  6. package/dist/agent-tools/tool-dispatch.js +2 -1
  7. package/dist/audit/handlers/list.query.js +9 -5
  8. package/dist/auth-email-password/bootstrap.d.ts +8 -5
  9. package/dist/auth-email-password/bootstrap.js +12 -4
  10. package/dist/auth-email-password/email-rate-limits.d.ts +4 -0
  11. package/dist/auth-email-password/email-rate-limits.js +13 -0
  12. package/dist/auth-email-password/email-templates.d.ts +4 -26
  13. package/dist/auth-email-password/email-templates.js +9 -101
  14. package/dist/auth-email-password/feature.js +24 -6
  15. package/dist/auth-email-password/handlers/change-password.write.d.ts +1 -1
  16. package/dist/auth-email-password/handlers/change-password.write.js +6 -2
  17. package/dist/auth-email-password/handlers/confirm-account-unlock.write.d.ts +1 -1
  18. package/dist/auth-email-password/handlers/invite-accept-with-login.write.d.ts +1 -1
  19. package/dist/auth-email-password/handlers/invite-accept.write.d.ts +1 -1
  20. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  21. package/dist/auth-email-password/handlers/invite-create.write.js +4 -4
  22. package/dist/auth-email-password/handlers/invite-signup-complete.write.d.ts +1 -1
  23. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  24. package/dist/auth-email-password/handlers/logout.write.d.ts +1 -1
  25. package/dist/auth-email-password/handlers/logout.write.js +6 -2
  26. package/dist/auth-email-password/handlers/request-account-unlock.write.d.ts +1 -1
  27. package/dist/auth-email-password/handlers/request-account-unlock.write.js +2 -4
  28. package/dist/auth-email-password/handlers/request-email-verification.write.d.ts +1 -1
  29. package/dist/auth-email-password/handlers/request-email-verification.write.js +2 -4
  30. package/dist/auth-email-password/handlers/request-password-reset.write.d.ts +1 -1
  31. package/dist/auth-email-password/handlers/request-password-reset.write.js +2 -4
  32. package/dist/auth-email-password/handlers/reset-password.write.d.ts +1 -1
  33. package/dist/auth-email-password/handlers/signup-confirm.write.d.ts +1 -1
  34. package/dist/auth-email-password/handlers/signup-confirm.write.js +3 -4
  35. package/dist/auth-email-password/handlers/signup-request.write.d.ts +1 -1
  36. package/dist/auth-email-password/handlers/signup-request.write.js +2 -1
  37. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  38. package/dist/auth-email-password/handlers/token-request-handler.d.ts +2 -3
  39. package/dist/auth-email-password/handlers/token-request-handler.js +2 -2
  40. package/dist/auth-email-password/handlers/verify-email.write.d.ts +1 -1
  41. package/dist/auth-email-password/index.d.ts +2 -2
  42. package/dist/auth-email-password/index.js +1 -1
  43. package/dist/auth-email-password/magic-link-mail.d.ts +3 -2
  44. package/dist/auth-email-password/magic-link-mail.js +19 -14
  45. package/dist/auth-email-password/mail-notifications.d.ts +32 -0
  46. package/dist/auth-email-password/mail-notifications.js +116 -0
  47. package/dist/auth-email-password/signup-activation.d.ts +1 -1
  48. package/dist/auth-email-password/signup-activation.js +2 -3
  49. package/dist/auth-email-password/web/auth-gate.js +16 -4
  50. package/dist/auth-foundation/types.js +2 -8
  51. package/dist/auth-mfa/feature.js +4 -4
  52. package/dist/auth-mfa/handlers/disable.write.d.ts +1 -1
  53. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.d.ts +1 -1
  54. package/dist/auth-mfa/handlers/enable-confirm.write.d.ts +1 -1
  55. package/dist/auth-mfa/handlers/enable-start-preauth.write.d.ts +1 -1
  56. package/dist/auth-mfa/handlers/enable-start.write.d.ts +1 -1
  57. package/dist/auth-mfa/handlers/regenerate-recovery.write.d.ts +1 -1
  58. package/dist/auth-mfa/handlers/verify.write.d.ts +1 -1
  59. package/dist/auth-mfa/hmac-token-codec.js +4 -4
  60. package/dist/auth-mfa/mfa-challenge-token.js +3 -3
  61. package/dist/auth-mfa/mfa-preauth-setup-token.js +3 -3
  62. package/dist/auth-mfa/mfa-setup-token.js +8 -8
  63. package/dist/billing-foundation/constants.d.ts +3 -3
  64. package/dist/billing-foundation/constants.js +5 -4
  65. package/dist/billing-foundation/consumer-protection/confirmation-mail.d.ts +32 -14
  66. package/dist/billing-foundation/consumer-protection/confirmation-mail.js +74 -32
  67. package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +3 -0
  68. package/dist/billing-foundation/consumer-protection/consent-gate.js +21 -2
  69. package/dist/billing-foundation/consumer-protection/issue-confirmation.js +3 -3
  70. package/dist/billing-foundation/consumer-protection/mail-notifications.d.ts +8 -0
  71. package/dist/billing-foundation/consumer-protection/mail-notifications.js +95 -0
  72. package/dist/billing-foundation/consumer-protection/register-consent.js +2 -0
  73. package/dist/billing-foundation/consumer-protection/register-termination.js +11 -1
  74. package/dist/billing-foundation/consumer-protection/termination-mail.d.ts +25 -13
  75. package/dist/billing-foundation/consumer-protection/termination-mail.js +11 -23
  76. package/dist/billing-foundation/consumer-protection/termination-notify.js +2 -2
  77. package/dist/billing-foundation/consumer-protection/termination-pages.js +1 -3
  78. package/dist/billing-foundation/consumer-protection/termination-receipt-limit.d.ts +6 -0
  79. package/dist/billing-foundation/consumer-protection/termination-receipt-limit.js +34 -0
  80. package/dist/billing-foundation/consumer-protection/termination-record.d.ts +2 -0
  81. package/dist/billing-foundation/consumer-protection/termination-record.js +7 -1
  82. package/dist/billing-foundation/consumer-protection/termination-request.js +31 -21
  83. package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +1 -1
  84. package/dist/billing-foundation/consumer-protection/termination-texts.js +6 -0
  85. package/dist/billing-foundation/consumer-protection/withdrawal-period.d.ts +10 -0
  86. package/dist/billing-foundation/consumer-protection/withdrawal-period.js +26 -0
  87. package/dist/billing-foundation/handlers/create-checkout-session.write.js +11 -5
  88. package/dist/billing-foundation/handlers/process-event.write.js +12 -8
  89. package/dist/billing-foundation/handlers/process-payment-event.write.js +1 -1
  90. package/dist/billing-foundation/i18n.js +3 -0
  91. package/dist/billing-foundation/subscription-tier-sync.d.ts +7 -1
  92. package/dist/billing-foundation/subscription-tier-sync.js +16 -9
  93. package/dist/billing-foundation/types.d.ts +7 -2
  94. package/dist/cap-counter/calendar-cap-usage-reservation.js +2 -0
  95. package/dist/cap-counter/enforce-cap.d.ts +18 -1
  96. package/dist/cap-counter/enforce-cap.js +49 -6
  97. package/dist/cap-counter/index.d.ts +1 -1
  98. package/dist/cap-counter/index.js +1 -1
  99. package/dist/cap-counter/with-cap-enforcement.d.ts +2 -0
  100. package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -1
  101. package/dist/cap-overview/web/cap-usage-cell.js +5 -4
  102. package/dist/channel-email/email-channel.d.ts +2 -2
  103. package/dist/channel-email/email-channel.js +101 -26
  104. package/dist/channel-email/feature.js +3 -3
  105. package/dist/channel-email/index.d.ts +1 -1
  106. package/dist/channel-email/index.js +1 -1
  107. package/dist/channel-email/pii-guard.js +10 -0
  108. package/dist/channel-email/smtp-transport.js +13 -0
  109. package/dist/channel-email/types.d.ts +8 -0
  110. package/dist/channel-in-app/handlers/mark-all-read.write.d.ts +1 -1
  111. package/dist/channel-in-app/handlers/mark-read.write.d.ts +1 -1
  112. package/dist/compliance-profiles/handlers/set-profile.write.d.ts +1 -1
  113. package/dist/config/handlers/reset.write.d.ts +1 -1
  114. package/dist/config/handlers/set.write.d.ts +1 -1
  115. package/dist/config/handlers/set.write.js +3 -4
  116. package/dist/config/resolver.d.ts +1 -0
  117. package/dist/config/resolver.js +11 -14
  118. package/dist/config/write-helpers.d.ts +2 -0
  119. package/dist/config/write-helpers.js +19 -0
  120. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -1
  121. package/dist/crypto-shredding/handlers/forget-subject.write.js +29 -19
  122. package/dist/custom-fields/handlers/update-tenant-field.write.js +0 -1
  123. package/dist/custom-fields/lib/value-schema.js +10 -11
  124. package/dist/custom-fields/wire-user-data-rights.js +7 -6
  125. package/dist/data-retention/index.d.ts +1 -0
  126. package/dist/data-retention/index.js +1 -0
  127. package/dist/data-retention/run-retention-cleanup.js +6 -6
  128. package/dist/delivery/attachment-ref.d.ts +41 -0
  129. package/dist/delivery/attachment-ref.js +78 -0
  130. package/dist/delivery/channel-context.d.ts +8 -4
  131. package/dist/delivery/channel-context.js +94 -2
  132. package/dist/delivery/constants.d.ts +1 -0
  133. package/dist/delivery/constants.js +1 -0
  134. package/dist/delivery/delivery-service.d.ts +4 -1
  135. package/dist/delivery/delivery-service.js +38 -32
  136. package/dist/delivery/feature.js +1 -1
  137. package/dist/delivery/handlers/resubscribe-address.write.d.ts +1 -1
  138. package/dist/delivery/handlers/resubscribe-user.write.d.ts +1 -1
  139. package/dist/delivery/handlers/set-preference.write.d.ts +1 -1
  140. package/dist/delivery/handlers/unsubscribe-address.write.d.ts +1 -1
  141. package/dist/delivery/handlers/unsubscribe-user.write.d.ts +1 -1
  142. package/dist/delivery/index.d.ts +5 -2
  143. package/dist/delivery/index.js +4 -1
  144. package/dist/delivery/jobs.js +66 -14
  145. package/dist/delivery/notify-factory.js +4 -1
  146. package/dist/delivery/testing.d.ts +4 -1
  147. package/dist/delivery/types.d.ts +26 -14
  148. package/dist/delivery/unsubscribe.js +4 -1
  149. package/dist/derivatives-sharp/render.js +1 -18
  150. package/dist/document-ingest-foundation/pages.js +4 -4
  151. package/dist/feature-toggles/handlers/set.write.d.ts +1 -1
  152. package/dist/feature-toggles/toggle-sync-signal.js +4 -4
  153. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  154. package/dist/file-foundation/index.d.ts +1 -0
  155. package/dist/file-foundation/index.js +1 -0
  156. package/dist/file-foundation/read-file-ref-content.d.ts +27 -0
  157. package/dist/file-foundation/read-file-ref-content.js +51 -0
  158. package/dist/files-tenant-data/hooks.js +4 -0
  159. package/dist/folders/web/folder-manager.js +3 -2
  160. package/dist/form-draft/db/queries/cleanup.js +4 -4
  161. package/dist/form-draft/db/queries/draft-count.js +2 -2
  162. package/dist/form-draft/db/queries/owned-file-refs.js +2 -2
  163. package/dist/form-draft/handlers/discard.write.d.ts +1 -1
  164. package/dist/form-draft/handlers/save.write.d.ts +1 -1
  165. package/dist/form-draft/release-file-refs.js +3 -2
  166. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +1 -1
  167. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +6 -6
  168. package/dist/inbound-mail-foundation/handlers/scope-visibility.d.ts +1 -1
  169. package/dist/inbound-mail-foundation/oauth-access-token.js +8 -3
  170. package/dist/inbound-mail-foundation/oauth-state.js +7 -7
  171. package/dist/inbound-mail-foundation/types.js +4 -4
  172. package/dist/inbound-mail-foundation/watch-supervisor.js +24 -13
  173. package/dist/inbound-provider-imap/imap-client.js +4 -3
  174. package/dist/jobs/db/queries/stale-run-sweep.d.ts +1 -1
  175. package/dist/jobs/db/queries/stale-run-sweep.js +12 -5
  176. package/dist/jobs/feature.js +5 -3
  177. package/dist/jobs/handlers/list.query.js +3 -1
  178. package/dist/jobs/handlers/retry.write.d.ts +1 -1
  179. package/dist/jobs/handlers/stale-run-sweep.job.d.ts +1 -1
  180. package/dist/jobs/handlers/stale-run-sweep.job.js +2 -2
  181. package/dist/jobs/handlers/trigger.write.d.ts +1 -1
  182. package/dist/jobs/job-run-logger.js +32 -10
  183. package/dist/jobs/tenant-job-run-table.js +3 -2
  184. package/dist/ledger/entity.js +3 -1
  185. package/dist/ledger/recurring.js +1 -3
  186. package/dist/managed-pages/branding.d.ts +2 -0
  187. package/dist/managed-pages/branding.js +24 -2
  188. package/dist/managed-pages/feature.js +1 -0
  189. package/dist/managed-pages/handlers/set.write.d.ts +1 -1
  190. package/dist/managed-pages/i18n.js +1 -0
  191. package/dist/managed-pages/screens/branding-screen.js +8 -1
  192. package/dist/page-render/branding.d.ts +1 -0
  193. package/dist/page-render/branding.js +1 -0
  194. package/dist/page-render/markdown.js +1 -1
  195. package/dist/personal-access-tokens/feature.js +1 -1
  196. package/dist/personal-access-tokens/handlers/create.write.d.ts +1 -1
  197. package/dist/personal-access-tokens/handlers/list.query.js +2 -1
  198. package/dist/personal-access-tokens/handlers/revoke.write.d.ts +1 -1
  199. package/dist/personal-access-tokens/revoke-for-user.js +2 -1
  200. package/dist/renderer-foundation/api.d.ts +13 -13
  201. package/dist/renderer-foundation/api.js +1 -1
  202. package/dist/renderer-foundation/constants.js +2 -4
  203. package/dist/renderer-foundation/feature.js +7 -7
  204. package/dist/renderer-foundation/index.d.ts +2 -1
  205. package/dist/renderer-foundation/index.js +1 -0
  206. package/dist/renderer-foundation/types.d.ts +94 -32
  207. package/dist/renderer-pdf/feature.js +7 -1
  208. package/dist/renderer-pdf/render-table-pdf.d.ts +27 -33
  209. package/dist/renderer-pdf/render-table-pdf.js +95 -34
  210. package/dist/secrets/feature.js +4 -3
  211. package/dist/secrets/handlers/delete.write.d.ts +1 -1
  212. package/dist/secrets/handlers/set.write.d.ts +1 -1
  213. package/dist/secrets/secrets-context.js +15 -3
  214. package/dist/sessions/db/queries/cleanup.js +2 -2
  215. package/dist/sessions/feature.js +1 -1
  216. package/dist/sessions/handlers/list.query.js +2 -1
  217. package/dist/sessions/handlers/revoke-all-for-user.write.d.ts +1 -1
  218. package/dist/sessions/handlers/revoke-all-others.write.d.ts +1 -1
  219. package/dist/sessions/handlers/revoke.write.d.ts +1 -1
  220. package/dist/shared/attachment-file-name.d.ts +3 -0
  221. package/dist/shared/attachment-file-name.js +35 -0
  222. package/dist/shared/chunked-entity-migration.d.ts +1 -0
  223. package/dist/shared/chunked-entity-migration.js +1 -1
  224. package/dist/shared/index.d.ts +3 -0
  225. package/dist/shared/index.js +3 -0
  226. package/dist/shared/is-tenant-db.js +1 -1
  227. package/dist/shared/mail-template-body.d.ts +7 -0
  228. package/dist/shared/mail-template-body.js +27 -0
  229. package/dist/shared/sharp-input-limits.d.ts +6 -0
  230. package/dist/shared/sharp-input-limits.js +22 -0
  231. package/dist/shared/signup-handover.js +2 -2
  232. package/dist/subscription-stripe/plugin-methods.js +18 -8
  233. package/dist/subscription-stripe/verify-webhook.d.ts +1 -1
  234. package/dist/tags/handlers/assign-tag.write.js +3 -1
  235. package/dist/tags/web/tag-chip.js +2 -0
  236. package/dist/template-resolver/api.d.ts +30 -2
  237. package/dist/template-resolver/api.js +42 -6
  238. package/dist/template-resolver/compile-document-body.d.ts +12 -0
  239. package/dist/template-resolver/compile-document-body.js +205 -0
  240. package/dist/template-resolver/constants.d.ts +13 -4
  241. package/dist/template-resolver/constants.js +32 -10
  242. package/dist/template-resolver/document-sanitizer.d.ts +32 -0
  243. package/dist/template-resolver/document-sanitizer.js +201 -0
  244. package/dist/template-resolver/document-schema.d.ts +21 -0
  245. package/dist/template-resolver/document-schema.js +316 -0
  246. package/dist/template-resolver/feature.d.ts +20 -0
  247. package/dist/template-resolver/feature.js +53 -6
  248. package/dist/template-resolver/handlers/bundle-import.d.ts +20 -0
  249. package/dist/template-resolver/handlers/bundle-import.js +147 -0
  250. package/dist/template-resolver/handlers/collection-set.write.d.ts +1 -1
  251. package/dist/template-resolver/handlers/collection-set.write.js +25 -2
  252. package/dist/template-resolver/handlers/copy-locale.write.d.ts +19 -0
  253. package/dist/template-resolver/handlers/copy-locale.write.js +134 -0
  254. package/dist/template-resolver/handlers/diff-to-system.query.d.ts +22 -0
  255. package/dist/template-resolver/handlers/diff-to-system.query.js +30 -0
  256. package/dist/template-resolver/handlers/discard-draft.write.d.ts +13 -0
  257. package/dist/template-resolver/handlers/discard-draft.write.js +37 -0
  258. package/dist/template-resolver/handlers/export-bundle.query.d.ts +35 -0
  259. package/dist/template-resolver/handlers/export-bundle.query.js +118 -0
  260. package/dist/template-resolver/handlers/find-by-id.query.d.ts +2 -0
  261. package/dist/template-resolver/handlers/find-by-id.query.js +9 -6
  262. package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +39 -0
  263. package/dist/template-resolver/handlers/import-bundle-system.write.js +36 -0
  264. package/dist/template-resolver/handlers/import-bundle.write.d.ts +40 -0
  265. package/dist/template-resolver/handlers/import-bundle.write.js +19 -0
  266. package/dist/template-resolver/handlers/layout-source.query.d.ts +31 -0
  267. package/dist/template-resolver/handlers/layout-source.query.js +87 -0
  268. package/dist/template-resolver/handlers/list.query.d.ts +4 -1
  269. package/dist/template-resolver/handlers/list.query.js +9 -8
  270. package/dist/template-resolver/handlers/override-diff.d.ts +20 -0
  271. package/dist/template-resolver/handlers/override-diff.js +41 -0
  272. package/dist/template-resolver/handlers/overview.query.d.ts +65 -0
  273. package/dist/template-resolver/handlers/overview.query.js +205 -0
  274. package/dist/template-resolver/handlers/preview.query.d.ts +12 -0
  275. package/dist/template-resolver/handlers/preview.query.js +24 -0
  276. package/dist/template-resolver/handlers/reset-to-system.write.d.ts +8 -0
  277. package/dist/template-resolver/handlers/reset-to-system.write.js +50 -0
  278. package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +8 -0
  279. package/dist/template-resolver/handlers/resource-link-pdf.write.js +32 -0
  280. package/dist/template-resolver/handlers/resource-remove.write.d.ts +9 -0
  281. package/dist/template-resolver/handlers/resource-remove.write.js +44 -0
  282. package/dist/template-resolver/handlers/resource-shared.d.ts +9 -0
  283. package/dist/template-resolver/handlers/resource-shared.js +14 -0
  284. package/dist/template-resolver/handlers/resource-upload.write.d.ts +13 -0
  285. package/dist/template-resolver/handlers/resource-upload.write.js +98 -0
  286. package/dist/template-resolver/handlers/send-test.write.d.ts +13 -0
  287. package/dist/template-resolver/handlers/send-test.write.js +108 -0
  288. package/dist/template-resolver/handlers/set.write.d.ts +5 -2
  289. package/dist/template-resolver/handlers/set.write.js +25 -3
  290. package/dist/template-resolver/handlers/shared.d.ts +9 -5
  291. package/dist/template-resolver/handlers/shared.js +6 -2
  292. package/dist/template-resolver/handlers/template-gates.d.ts +36 -0
  293. package/dist/template-resolver/handlers/template-gates.js +142 -0
  294. package/dist/template-resolver/handlers/template-write.d.ts +45 -0
  295. package/dist/template-resolver/handlers/template-write.js +141 -0
  296. package/dist/template-resolver/handlers/tenant-overrides.query.d.ts +49 -0
  297. package/dist/template-resolver/handlers/tenant-overrides.query.js +112 -0
  298. package/dist/template-resolver/handlers/toggle-status.write.d.ts +27 -2
  299. package/dist/template-resolver/handlers/toggle-status.write.js +47 -15
  300. package/dist/template-resolver/handlers/upsert-system.write.d.ts +5 -8
  301. package/dist/template-resolver/handlers/upsert-system.write.js +14 -59
  302. package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +5 -8
  303. package/dist/template-resolver/handlers/upsert-tenant.write.js +11 -62
  304. package/dist/template-resolver/handlers/usage.query.d.ts +17 -0
  305. package/dist/template-resolver/handlers/usage.query.js +24 -0
  306. package/dist/template-resolver/handlers/validate.query.d.ts +74 -0
  307. package/dist/template-resolver/handlers/validate.query.js +80 -0
  308. package/dist/template-resolver/index.d.ts +19 -1
  309. package/dist/template-resolver/index.js +17 -1
  310. package/dist/template-resolver/layout-appearance.d.ts +10 -0
  311. package/dist/template-resolver/layout-appearance.js +26 -0
  312. package/dist/template-resolver/layout-regions.d.ts +23 -0
  313. package/dist/template-resolver/layout-regions.js +125 -0
  314. package/dist/template-resolver/linked-resources.d.ts +17 -0
  315. package/dist/template-resolver/linked-resources.js +75 -0
  316. package/dist/template-resolver/pdf-constants.d.ts +7 -0
  317. package/dist/template-resolver/pdf-constants.js +8 -0
  318. package/dist/template-resolver/preview-display-html.d.ts +7 -0
  319. package/dist/template-resolver/preview-display-html.js +27 -0
  320. package/dist/template-resolver/print-document.d.ts +1 -0
  321. package/dist/template-resolver/print-document.js +55 -0
  322. package/dist/template-resolver/qualified-names.d.ts +34 -0
  323. package/dist/template-resolver/qualified-names.js +34 -0
  324. package/dist/template-resolver/record-mapping.d.ts +2 -0
  325. package/dist/template-resolver/record-mapping.js +21 -0
  326. package/dist/template-resolver/resource-image.d.ts +15 -0
  327. package/dist/template-resolver/resource-image.js +34 -0
  328. package/dist/template-resolver/seeding.d.ts +14 -1
  329. package/dist/template-resolver/seeding.js +125 -18
  330. package/dist/template-resolver/store-template-resource.d.ts +64 -0
  331. package/dist/template-resolver/store-template-resource.js +264 -0
  332. package/dist/template-resolver/table.d.ts +150 -8
  333. package/dist/template-resolver/table.js +20 -2
  334. package/dist/template-resolver/template-bundle.d.ts +36 -0
  335. package/dist/template-resolver/template-bundle.js +60 -0
  336. package/dist/template-resolver/template-diff.d.ts +7 -0
  337. package/dist/template-resolver/template-diff.js +68 -0
  338. package/dist/template-resolver/template-draft.d.ts +51 -0
  339. package/dist/template-resolver/template-draft.js +72 -0
  340. package/dist/template-resolver/template-meta.d.ts +85 -0
  341. package/dist/template-resolver/template-meta.js +145 -0
  342. package/dist/template-resolver/template-preview.d.ts +103 -0
  343. package/dist/template-resolver/template-preview.js +418 -0
  344. package/dist/template-resolver/template-resources.d.ts +19 -0
  345. package/dist/template-resolver/template-resources.js +73 -0
  346. package/dist/template-resolver/template-usage.d.ts +16 -0
  347. package/dist/template-resolver/template-usage.js +35 -0
  348. package/dist/template-resolver/template-validation.d.ts +22 -0
  349. package/dist/template-resolver/template-validation.js +173 -0
  350. package/dist/template-resolver/testing.js +5 -5
  351. package/dist/template-resolver/user-content-table.d.ts +14 -8
  352. package/dist/template-resolver/web/client-plugin.d.ts +1 -0
  353. package/dist/template-resolver/web/client-plugin.js +12 -7
  354. package/dist/template-resolver/web/document-editor-extensions.d.ts +18 -0
  355. package/dist/template-resolver/web/document-editor-extensions.js +145 -0
  356. package/dist/template-resolver/web/document-editor.d.ts +4 -0
  357. package/dist/template-resolver/web/document-editor.js +17 -0
  358. package/dist/template-resolver/web/document-tiptap-editor.d.ts +3 -0
  359. package/dist/template-resolver/web/document-tiptap-editor.js +492 -0
  360. package/dist/template-resolver/web/document-toolbar-blocks.d.ts +41 -0
  361. package/dist/template-resolver/web/document-toolbar-blocks.js +19 -0
  362. package/dist/template-resolver/web/editor-handle.d.ts +3 -0
  363. package/dist/template-resolver/web/editor-handle.js +24 -0
  364. package/dist/template-resolver/web/i18n.js +91 -0
  365. package/dist/template-resolver/web/index.d.ts +5 -0
  366. package/dist/template-resolver/web/index.js +5 -0
  367. package/dist/template-resolver/web/placeholder-line-editor-lazy.d.ts +4 -0
  368. package/dist/template-resolver/web/placeholder-line-editor-lazy.js +16 -0
  369. package/dist/template-resolver/web/placeholder-line-editor.d.ts +17 -0
  370. package/dist/template-resolver/web/placeholder-line-editor.js +94 -0
  371. package/dist/template-resolver/web/placeholder-text.d.ts +4 -0
  372. package/dist/template-resolver/web/placeholder-text.js +34 -0
  373. package/dist/template-resolver/web/use-stable-by-key.d.ts +1 -0
  374. package/dist/template-resolver/web/use-stable-by-key.js +13 -0
  375. package/dist/tenant/handlers/add-member.write.d.ts +1 -1
  376. package/dist/tenant/handlers/cancel-invitation.write.d.ts +1 -1
  377. package/dist/tenant/handlers/create.write.d.ts +1 -1
  378. package/dist/tenant/handlers/remove-member.write.d.ts +1 -1
  379. package/dist/tenant/handlers/team-list.query.js +3 -2
  380. package/dist/tenant/handlers/toggle-enabled.write.d.ts +2 -2
  381. package/dist/tenant/handlers/update-member-roles.write.d.ts +1 -1
  382. package/dist/tenant/handlers/update.write.d.ts +1 -1
  383. package/dist/tenant/seeding.js +31 -6
  384. package/dist/tenant-handover/handlers/claim.write.d.ts +1 -1
  385. package/dist/tenant-lifecycle/handlers/cancel-destruction.write.d.ts +2 -2
  386. package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +2 -1
  387. package/dist/tenant-lifecycle/handlers/request-destruction.write.d.ts +1 -1
  388. package/dist/tier-engine/feature.js +9 -3
  389. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +1 -1
  390. package/dist/user/db/queries/stream-tenant-backfill.js +4 -4
  391. package/dist/user/handlers/create.write.d.ts +1 -1
  392. package/dist/user/handlers/detail.query.js +2 -1
  393. package/dist/user/handlers/update.write.d.ts +1 -1
  394. package/dist/user/resolve-display-names.js +5 -9
  395. package/dist/user/seeding.js +20 -1
  396. package/dist/user-data-rights/db/queries/forget-cleanup.d.ts +2 -2
  397. package/dist/user-data-rights/email-templates.d.ts +1 -29
  398. package/dist/user-data-rights/email-templates.js +5 -106
  399. package/dist/user-data-rights/feature.js +53 -35
  400. package/dist/user-data-rights/handlers/cancel-deletion.write.d.ts +2 -2
  401. package/dist/user-data-rights/handlers/cancel-deletion.write.js +2 -1
  402. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.d.ts +1 -1
  403. package/dist/user-data-rights/handlers/lift-restriction.write.d.ts +1 -1
  404. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +1 -1
  405. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +1 -1
  406. package/dist/user-data-rights/handlers/request-deletion.write.js +5 -7
  407. package/dist/user-data-rights/handlers/request-export.write.d.ts +1 -1
  408. package/dist/user-data-rights/handlers/restrict-account.write.d.ts +1 -1
  409. package/dist/user-data-rights/handlers/run-forget-cleanup.write.d.ts +1 -1
  410. package/dist/user-data-rights/lib/default-mailers.d.ts +15 -7
  411. package/dist/user-data-rights/lib/default-mailers.js +100 -48
  412. package/dist/user-data-rights/lib/update-user-lifecycle.js +1 -1
  413. package/dist/user-data-rights/mail-notifications.d.ts +13 -0
  414. package/dist/user-data-rights/mail-notifications.js +118 -0
  415. package/dist/user-data-rights/web/privacy-center-screen.js +2 -1
  416. package/dist/user-profile/handlers/change-email.write.d.ts +1 -1
  417. package/dist/user-profile/web/profile-screen.js +2 -1
  418. package/dist/waitlist/feature.js +10 -0
  419. package/dist/waitlist/handlers/invite.write.d.ts +1 -1
  420. package/dist/waitlist/handlers/reject.write.d.ts +1 -1
  421. package/dist/waitlist/handlers/submit.write.d.ts +1 -1
  422. package/dist/waitlist/handlers/submit.write.js +3 -4
  423. package/dist/waitlist/mail.d.ts +19 -6
  424. package/dist/waitlist/mail.js +50 -14
  425. package/dist/waitlist/options.js +1 -1
  426. package/dist/workflow-runner/event-trigger.js +2 -2
  427. package/dist/workflow-runner/handlers/resume-run.write.js +7 -2
  428. package/package.json +37 -17
  429. package/src/admin-shell/changes.json +6 -0
  430. package/src/audit/changes.json +6 -0
  431. package/src/auth-email-password/changes.json +51 -0
  432. package/src/billing-foundation/changes.json +43 -0
  433. package/src/cap-counter/changes.json +6 -0
  434. package/src/channel-email/changes.json +19 -0
  435. package/src/config/changes.json +6 -0
  436. package/src/crypto-shredding/changes.json +6 -0
  437. package/src/custom-fields/changes.json +6 -0
  438. package/src/data-retention/changes.json +6 -0
  439. package/src/delivery/changes.json +66 -0
  440. package/src/file-foundation/changes.json +6 -0
  441. package/src/files-tenant-data/changes.json +6 -0
  442. package/src/inbound-mail-foundation/changes.json +6 -0
  443. package/src/jobs/changes.json +19 -0
  444. package/src/ledger/changes.json +7 -0
  445. package/src/managed-pages/changes.json +6 -0
  446. package/src/renderer-foundation/changes.json +39 -0
  447. package/src/renderer-pdf/changes.json +12 -0
  448. package/src/secrets/changes.json +6 -0
  449. package/src/shared/changes.json +6 -0
  450. package/src/subscription-stripe/changes.json +6 -0
  451. package/src/template-resolver/changes.json +186 -0
  452. package/src/tier-engine/changes.json +6 -0
  453. package/src/user/changes.json +6 -0
  454. package/src/user-data-rights/changes.json +13 -0
  455. package/src/user-profile/changes.json +1 -1
  456. package/src/waitlist/changes.json +7 -0
  457. package/src/workflow-runner/changes.json +6 -0
  458. package/dist/renderer-simple/feature.d.ts +0 -10
  459. package/dist/renderer-simple/feature.js +0 -42
  460. package/dist/renderer-simple/index.d.ts +0 -3
  461. package/dist/renderer-simple/index.js +0 -2
  462. package/dist/renderer-simple/mail-blocks.d.ts +0 -21
  463. package/dist/renderer-simple/mail-blocks.js +0 -107
  464. package/dist/renderer-simple/resolve-variables.d.ts +0 -7
  465. package/dist/renderer-simple/resolve-variables.js +0 -47
  466. package/dist/renderer-simple/simple-renderer.d.ts +0 -24
  467. package/dist/renderer-simple/simple-renderer.js +0 -200
  468. package/src/renderer-simple/changes.json +0 -27
@@ -26,26 +26,29 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
26
26
  kind: {
27
27
  readonly type: "select";
28
28
  readonly description?: string;
29
- readonly options: readonly ["notification", "mail-html", "document-pdf", "image-snapshot", "text-block", "ai-prompt"];
29
+ readonly options: readonly ["mail", "document-pdf", "image-snapshot", "notification", "text-block", "snippet", "ai-prompt", "mail-layout", "pdf-layout"];
30
30
  readonly required?: boolean;
31
31
  readonly sortable?: boolean;
32
32
  readonly filterable?: boolean;
33
33
  readonly sensitive?: boolean;
34
- readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block" | undefined;
34
+ readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block" | undefined;
35
35
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
36
36
  readonly display?: "radio" | "dropdown";
37
37
  readonly optionTones?: {
38
38
  readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
39
39
  readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
40
40
  readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
41
- readonly "mail-html"?: "bad" | "neutral" | "ok" | "warn" | undefined;
41
+ readonly mail?: "bad" | "neutral" | "ok" | "warn" | undefined;
42
+ readonly "mail-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
42
43
  readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
44
+ readonly "pdf-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
45
+ readonly snippet?: "bad" | "neutral" | "ok" | "warn" | undefined;
43
46
  readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
44
47
  } | undefined;
45
48
  readonly optionsQuery?: string;
46
49
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
47
50
  readonly optionsAvailabilityQuery?: string;
48
- readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block">[] | undefined;
51
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block">[] | undefined;
49
52
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
50
53
  required: true;
51
54
  };
@@ -190,6 +193,22 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
190
193
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
191
194
  required: false;
192
195
  };
196
+ meta: {
197
+ readonly type: "longText";
198
+ readonly description?: string;
199
+ readonly maxLength?: number;
200
+ readonly required?: boolean;
201
+ readonly encrypted?: boolean;
202
+ readonly sensitive?: boolean;
203
+ readonly readAsInstruction?: boolean;
204
+ readonly default?: string;
205
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
206
+ readonly multiline?: boolean | {
207
+ readonly rows?: number;
208
+ };
209
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
210
+ required: false;
211
+ };
193
212
  scope: {
194
213
  readonly type: "select";
195
214
  readonly description?: string;
@@ -258,6 +277,56 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
258
277
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
259
278
  required: true;
260
279
  };
280
+ draft: {
281
+ readonly type: "longText";
282
+ readonly description?: string;
283
+ readonly maxLength?: number;
284
+ readonly required?: boolean;
285
+ readonly encrypted?: boolean;
286
+ readonly sensitive?: boolean;
287
+ readonly readAsInstruction?: boolean;
288
+ readonly default?: string;
289
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
290
+ readonly multiline?: boolean | {
291
+ readonly rows?: number;
292
+ };
293
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
294
+ required: false;
295
+ };
296
+ activeVersion: {
297
+ readonly type: "number";
298
+ readonly description?: string;
299
+ readonly required?: boolean;
300
+ readonly sortable?: boolean;
301
+ readonly filterable?: boolean;
302
+ readonly sensitive?: boolean;
303
+ readonly default?: number;
304
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
305
+ readonly min?: number;
306
+ readonly max?: number;
307
+ readonly integer?: boolean;
308
+ readonly unit?: string | {
309
+ readonly field: string;
310
+ };
311
+ readonly grouping?: boolean;
312
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
313
+ required: false;
314
+ };
315
+ activeSince: {
316
+ readonly type: "timestamp";
317
+ readonly description?: string;
318
+ readonly required?: boolean;
319
+ readonly sortable?: boolean;
320
+ readonly filterable?: boolean;
321
+ readonly sensitive?: boolean;
322
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
323
+ readonly locatedBy?: string;
324
+ readonly min?: string;
325
+ readonly max?: string;
326
+ readonly locale?: string;
327
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
328
+ required: false;
329
+ };
261
330
  }, "tenant">;
262
331
  export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framework/db").EntityTable<import("@cosmicdrift/kumiko-types/fields").EntityDefinition<{
263
332
  slug: {
@@ -286,26 +355,29 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
286
355
  kind: {
287
356
  readonly type: "select";
288
357
  readonly description?: string;
289
- readonly options: readonly ["notification", "mail-html", "document-pdf", "image-snapshot", "text-block", "ai-prompt"];
358
+ readonly options: readonly ["mail", "document-pdf", "image-snapshot", "notification", "text-block", "snippet", "ai-prompt", "mail-layout", "pdf-layout"];
290
359
  readonly required?: boolean;
291
360
  readonly sortable?: boolean;
292
361
  readonly filterable?: boolean;
293
362
  readonly sensitive?: boolean;
294
- readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block" | undefined;
363
+ readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block" | undefined;
295
364
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
296
365
  readonly display?: "radio" | "dropdown";
297
366
  readonly optionTones?: {
298
367
  readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
299
368
  readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
300
369
  readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
301
- readonly "mail-html"?: "bad" | "neutral" | "ok" | "warn" | undefined;
370
+ readonly mail?: "bad" | "neutral" | "ok" | "warn" | undefined;
371
+ readonly "mail-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
302
372
  readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
373
+ readonly "pdf-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
374
+ readonly snippet?: "bad" | "neutral" | "ok" | "warn" | undefined;
303
375
  readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
304
376
  } | undefined;
305
377
  readonly optionsQuery?: string;
306
378
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
307
379
  readonly optionsAvailabilityQuery?: string;
308
- readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block">[] | undefined;
380
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block">[] | undefined;
309
381
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
310
382
  required: true;
311
383
  };
@@ -450,6 +522,22 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
450
522
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
451
523
  required: false;
452
524
  };
525
+ meta: {
526
+ readonly type: "longText";
527
+ readonly description?: string;
528
+ readonly maxLength?: number;
529
+ readonly required?: boolean;
530
+ readonly encrypted?: boolean;
531
+ readonly sensitive?: boolean;
532
+ readonly readAsInstruction?: boolean;
533
+ readonly default?: string;
534
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
535
+ readonly multiline?: boolean | {
536
+ readonly rows?: number;
537
+ };
538
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
539
+ required: false;
540
+ };
453
541
  scope: {
454
542
  readonly type: "select";
455
543
  readonly description?: string;
@@ -518,6 +606,56 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
518
606
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
519
607
  required: true;
520
608
  };
609
+ draft: {
610
+ readonly type: "longText";
611
+ readonly description?: string;
612
+ readonly maxLength?: number;
613
+ readonly required?: boolean;
614
+ readonly encrypted?: boolean;
615
+ readonly sensitive?: boolean;
616
+ readonly readAsInstruction?: boolean;
617
+ readonly default?: string;
618
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
619
+ readonly multiline?: boolean | {
620
+ readonly rows?: number;
621
+ };
622
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
623
+ required: false;
624
+ };
625
+ activeVersion: {
626
+ readonly type: "number";
627
+ readonly description?: string;
628
+ readonly required?: boolean;
629
+ readonly sortable?: boolean;
630
+ readonly filterable?: boolean;
631
+ readonly sensitive?: boolean;
632
+ readonly default?: number;
633
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
634
+ readonly min?: number;
635
+ readonly max?: number;
636
+ readonly integer?: boolean;
637
+ readonly unit?: string | {
638
+ readonly field: string;
639
+ };
640
+ readonly grouping?: boolean;
641
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
642
+ required: false;
643
+ };
644
+ activeSince: {
645
+ readonly type: "timestamp";
646
+ readonly description?: string;
647
+ readonly required?: boolean;
648
+ readonly sortable?: boolean;
649
+ readonly filterable?: boolean;
650
+ readonly sensitive?: boolean;
651
+ readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
652
+ readonly locatedBy?: string;
653
+ readonly min?: string;
654
+ readonly max?: string;
655
+ readonly locale?: string;
656
+ } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
657
+ required: false;
658
+ };
521
659
  }, "tenant">>;
522
660
  export type EntityAuditColumns = {
523
661
  readonly insertedAt: Temporal.Instant;
@@ -538,7 +676,11 @@ export type TemplateResourceRow = {
538
676
  readonly contentFormat: string;
539
677
  readonly variableSchema: string | null;
540
678
  readonly linkedResources: string | null;
679
+ readonly meta: string | null;
541
680
  readonly scope: string;
542
681
  readonly parentTemplateId: string | null;
543
682
  readonly status: string;
683
+ readonly draft: string | null;
684
+ readonly activeVersion: number | null;
685
+ readonly activeSince: Temporal.Instant | null;
544
686
  } & EntityAuditColumns;
@@ -1,10 +1,18 @@
1
1
  import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
2
- import { createEntity, createLongTextField, createSelectField, createTextField, } from "@cosmicdrift/kumiko-framework/engine";
2
+ import { createEntity, createLongTextField, createNumberField, createSelectField, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { CONTENT_FORMATS, TEMPLATE_KINDS, TEMPLATE_SCOPES, TEMPLATE_STATUSES, } from "./constants.js";
4
+ // Stored v1 events name the kind "mail-html", which is now "mail".
5
+ const renameMailHtmlKind = {
6
+ fromVersion: 1,
7
+ toVersion: 2,
8
+ transform: (fields) => (fields["kind"] === "mail-html" ? { ...fields, kind: "mail" } : fields),
9
+ };
4
10
  // TemplateResource — strukturierte Template-Definition mit Tenant-
5
11
  // Override-Hierarchie, Locale-Fallback und Resource-Linking via
6
12
  // file-foundation. Pro (tenantId, slug, kind, locale) genau eine Row;
7
- // scope/status/version differenzieren Lifecycle.
13
+ // scope/status/version differenzieren Lifecycle. Der Entwurf neben einer
14
+ // aktiven Fassung liegt in `draft`; die Hauptfelder bleiben die ausgelieferte
15
+ // Fassung.
8
16
  //
9
17
  // `variableSchema` + `linkedResources` sind JSON-Strings in longText
10
18
  // (Pattern aus compliance-profiles — kein dedizierter jsonbField im
@@ -32,9 +40,17 @@ export const templateResourceEntity = createEntity({
32
40
  contentFormat: createSelectField({ required: true, options: [...CONTENT_FORMATS] }),
33
41
  variableSchema: createLongTextField({ personal: false, reason: "technical_reference" }),
34
42
  linkedResources: createLongTextField({ personal: false, reason: "technical_reference" }),
43
+ // Per-kind JSON (mail: subject, preview text, layout slug, ...), validated
44
+ // against template-meta.ts on write. Authored by TenantAdmin/Operator.
45
+ meta: createLongTextField({ personal: false, reason: "is_business_data" }),
35
46
  scope: createSelectField({ required: true, options: [...TEMPLATE_SCOPES] }),
36
47
  parentTemplateId: createTextField({ personal: false, reason: "technical_reference" }),
37
48
  status: createSelectField({ required: true, options: [...TEMPLATE_STATUSES] }),
49
+ // JSON of the unpublished edit beside the active version (see template-draft.ts).
50
+ draft: createLongTextField({ personal: false, reason: "is_business_data" }),
51
+ // `version` counts every save including drafts; these two describe the served version.
52
+ activeVersion: createNumberField({ integer: true, min: 1 }),
53
+ activeSince: createTimestampField({}),
38
54
  },
39
55
  indexes: [
40
56
  {
@@ -43,5 +59,7 @@ export const templateResourceEntity = createEntity({
43
59
  name: "read_template_resources_unique",
44
60
  },
45
61
  ],
62
+ eventVersion: 2,
63
+ eventMigrations: [renameMailHtmlKind],
46
64
  });
47
65
  export const templateResourcesTable = buildEntityTable("template-resource", templateResourceEntity);
@@ -0,0 +1,36 @@
1
+ import * as z from "zod";
2
+ export declare const templateBundleSchema: z.ZodObject<{
3
+ slug: z.ZodString;
4
+ kind: z.ZodEnum<{
5
+ "ai-prompt": "ai-prompt";
6
+ "document-pdf": "document-pdf";
7
+ "image-snapshot": "image-snapshot";
8
+ mail: "mail";
9
+ "mail-layout": "mail-layout";
10
+ "pdf-layout": "pdf-layout";
11
+ }>;
12
+ contentFormat: z.ZodEnum<{
13
+ html: "html";
14
+ markdown: "markdown";
15
+ mjml: "mjml";
16
+ plain: "plain";
17
+ }>;
18
+ variableSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
19
+ locales: z.ZodRecord<z.ZodString, z.ZodObject<{
20
+ body: z.ZodString;
21
+ meta: z.ZodOptional<z.ZodUnknown>;
22
+ }, z.core.$strict>>;
23
+ resources: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
24
+ fileName: z.ZodString;
25
+ contentType: z.ZodString;
26
+ base64: z.ZodString;
27
+ purpose: z.ZodOptional<z.ZodEnum<{
28
+ attachment: "attachment";
29
+ }>>;
30
+ }, z.core.$strict>>>;
31
+ pdfAttachments: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
32
+ templateSlug: z.ZodString;
33
+ fileName: z.ZodString;
34
+ }, z.core.$strict>>>;
35
+ }, z.core.$strict>;
36
+ export type TemplateBundle = z.infer<typeof templateBundleSchema>;
@@ -0,0 +1,60 @@
1
+ import * as z from "zod";
2
+ import { CONTENT_FORMATS, UPSERT_KINDS } from "./constants.js";
3
+ import { isDocumentResourceKey } from "./document-schema.js";
4
+ import { templatePdfAttachmentLinkSchema } from "./linked-resources.js";
5
+ import { templateSlugSchema } from "./template-meta.js";
6
+ const MAX_RESOURCES = 20;
7
+ const MAX_RESOURCE_BYTES = 2 * 1024 * 1024;
8
+ const MAX_BASE64_LENGTH = Math.ceil(MAX_RESOURCE_BYTES / 3) * 4;
9
+ const STRICT_BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
10
+ const CONTENT_TYPE = /^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/i;
11
+ const UNSAFE_FILE_NAME_CHARACTERS = /[/\\";]|\p{Cc}/u;
12
+ const bundleLocaleSchema = z
13
+ .string()
14
+ .min(2)
15
+ .max(8)
16
+ .regex(/^[a-z]{2}(-[a-z]{2})?$/i, "locale must be ISO 639-1 (e.g. de, en, en-us)");
17
+ const bundleFileNameSchema = z
18
+ .string()
19
+ .min(1)
20
+ .max(200)
21
+ .refine((name) => !UNSAFE_FILE_NAME_CHARACTERS.test(name) && !name.includes(".."), {
22
+ message: 'file name must not contain / \\ " ; control characters or ".."',
23
+ });
24
+ const bundleResourceSchema = z
25
+ .object({
26
+ fileName: bundleFileNameSchema,
27
+ contentType: z.string().max(100).regex(CONTENT_TYPE, "content type must be type/subtype"),
28
+ base64: z.string().max(MAX_BASE64_LENGTH).regex(STRICT_BASE64, "base64 is not valid"),
29
+ // Absent means an image the body embeds; "attachment" is a file attached to the mail.
30
+ purpose: z.enum(["attachment"]).optional(),
31
+ })
32
+ .strict();
33
+ const pdfAttachmentLinkBodySchema = templatePdfAttachmentLinkSchema.omit({ kind: true });
34
+ const bundleLocaleEntrySchema = z
35
+ .object({ body: z.string().max(200_000), meta: z.unknown().optional() })
36
+ .strict();
37
+ export const templateBundleSchema = z
38
+ .object({
39
+ slug: templateSlugSchema,
40
+ kind: z.enum(UPSERT_KINDS),
41
+ contentFormat: z.enum(CONTENT_FORMATS),
42
+ variableSchema: z.record(z.string(), z.unknown()).optional(),
43
+ locales: z
44
+ .record(bundleLocaleSchema, bundleLocaleEntrySchema)
45
+ .refine((locales) => Object.keys(locales).length >= 1, {
46
+ message: "a bundle needs at least one locale",
47
+ }),
48
+ resources: z
49
+ .record(z.string().refine(isDocumentResourceKey, { message: "not a valid resource key" }), bundleResourceSchema)
50
+ .refine((resources) => Object.keys(resources).length <= MAX_RESOURCES, {
51
+ message: `a bundle holds at most ${MAX_RESOURCES} resources`,
52
+ })
53
+ .default({}),
54
+ // PDFs rendered from document templates at send time; nothing to store, so no bytes.
55
+ pdfAttachments: z
56
+ .record(z.string().refine(isDocumentResourceKey, { message: "not a valid resource key" }), pdfAttachmentLinkBodySchema)
57
+ .default({}),
58
+ })
59
+ .strict()
60
+ .refine((bundle) => Object.keys(bundle.pdfAttachments).every((key) => !(key in bundle.resources)), { message: "a key is used by a resource and a PDF attachment", path: ["pdfAttachments"] });
@@ -0,0 +1,7 @@
1
+ export type TemplateDiffChange = "same" | "added" | "removed";
2
+ export type TemplateDiffBlock = {
3
+ readonly change: TemplateDiffChange;
4
+ readonly content: string;
5
+ };
6
+ export declare function splitTemplateBlocks(content: string, contentFormat: string): string[];
7
+ export declare function diffTemplateBlocks(system: readonly string[], tenant: readonly string[]): TemplateDiffBlock[];
@@ -0,0 +1,68 @@
1
+ import { withParsedDocument } from "./document-sanitizer.js";
2
+ // Beyond this the quadratic LCS table is not worth it for a preview.
3
+ const MAX_LCS_CELLS = 1_000_000;
4
+ function splitHtmlBlocks(content) {
5
+ return withParsedDocument(content, (body) => {
6
+ const blocks = [];
7
+ for (const node of Array.from(body.childNodes)) {
8
+ const markup = "outerHTML" in node && typeof node.outerHTML === "string" ? node.outerHTML : "";
9
+ const text = markup === "" ? (node.textContent ?? "").trim() : markup;
10
+ if (text !== "")
11
+ blocks.push(text);
12
+ }
13
+ return blocks;
14
+ });
15
+ }
16
+ export function splitTemplateBlocks(content, contentFormat) {
17
+ if (contentFormat === "html")
18
+ return splitHtmlBlocks(content);
19
+ return content
20
+ .split(/\r?\n[ \t]*\r?\n/)
21
+ .map((block) => block.trim())
22
+ .filter((block) => block !== "");
23
+ }
24
+ // "removed" = only in the system template, "added" = only in the tenant version.
25
+ export function diffTemplateBlocks(system, tenant) {
26
+ if (system.length * tenant.length > MAX_LCS_CELLS) {
27
+ return [
28
+ ...system.map((content) => ({ change: "removed", content })),
29
+ ...tenant.map((content) => ({ change: "added", content })),
30
+ ];
31
+ }
32
+ const rows = system.length;
33
+ const cols = tenant.length;
34
+ const width = cols + 1;
35
+ // lengths[i * width + j] = LCS length of system[i..] and tenant[j..]
36
+ const lengths = new Uint32Array((rows + 1) * width);
37
+ const lengthAt = (i, j) => lengths[i * width + j] ?? 0;
38
+ for (let i = rows - 1; i >= 0; i--) {
39
+ for (let j = cols - 1; j >= 0; j--) {
40
+ lengths[i * width + j] =
41
+ system[i] === tenant[j]
42
+ ? lengthAt(i + 1, j + 1) + 1
43
+ : Math.max(lengthAt(i + 1, j), lengthAt(i, j + 1));
44
+ }
45
+ }
46
+ const result = [];
47
+ let i = 0;
48
+ let j = 0;
49
+ while (i < rows || j < cols) {
50
+ const systemBlock = system[i];
51
+ const tenantBlock = tenant[j];
52
+ if (systemBlock !== undefined && systemBlock === tenantBlock) {
53
+ result.push({ change: "same", content: systemBlock });
54
+ i++;
55
+ j++;
56
+ }
57
+ else if (systemBlock !== undefined &&
58
+ (tenantBlock === undefined || lengthAt(i + 1, j) >= lengthAt(i, j + 1))) {
59
+ result.push({ change: "removed", content: systemBlock });
60
+ i++;
61
+ }
62
+ else if (tenantBlock !== undefined) {
63
+ result.push({ change: "added", content: tenantBlock });
64
+ j++;
65
+ }
66
+ }
67
+ return result;
68
+ }
@@ -0,0 +1,51 @@
1
+ import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
2
+ import { type ContentFormat } from "./constants.js";
3
+ import type { TemplateResourceRow } from "./table.js";
4
+ export type TemplateDraft = {
5
+ readonly content: string | null;
6
+ readonly contentFormat: ContentFormat;
7
+ readonly variableSchema: string;
8
+ readonly meta: string | null;
9
+ readonly title: string | null;
10
+ readonly folder: string | null;
11
+ readonly parentTemplateId: string | null;
12
+ };
13
+ export declare function parseTemplateDraft(raw: string | null): TemplateDraft | null;
14
+ export declare function serializeTemplateDraft(draft: TemplateDraft): string;
15
+ export declare function activeVersionOf(row: TemplateResourceRow): number;
16
+ export declare function servedVersionOf(row: TemplateResourceRow): number;
17
+ export declare function activeSinceOf(row: TemplateResourceRow): Temporal.Instant;
18
+ export type ActiveInfo = {
19
+ readonly version: number;
20
+ readonly since: Temporal.Instant;
21
+ };
22
+ export type WorkingRow = TemplateResourceRow & {
23
+ readonly active: ActiveInfo | null;
24
+ };
25
+ export declare function isHiddenSystemDraft(user: {
26
+ readonly roles: readonly string[];
27
+ }, row: Pick<TemplateResourceRow, "scope" | "status">): boolean;
28
+ export declare function draftViewerTenantId(user: {
29
+ readonly tenantId: string;
30
+ readonly roles: readonly string[];
31
+ }, row: TemplateResourceRow): string;
32
+ export declare function toWorkingRow(row: TemplateResourceRow, viewerTenantId: string): WorkingRow;
33
+ export declare function servedStampChanges(row: {
34
+ readonly version: number;
35
+ } | null): {
36
+ activeVersion: number;
37
+ activeSince: globalThis.Temporal.Instant;
38
+ };
39
+ export declare function activeStampChanges(row: {
40
+ readonly version: number;
41
+ } | null): {
42
+ activeVersion: number;
43
+ activeSince: globalThis.Temporal.Instant;
44
+ status: string;
45
+ };
46
+ export declare function activationChanges(row: TemplateResourceRow | null): {
47
+ activeVersion: number;
48
+ activeSince: globalThis.Temporal.Instant;
49
+ status: string;
50
+ draft: null;
51
+ };
@@ -0,0 +1,72 @@
1
+ import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
2
+ import * as z from "zod";
3
+ import { CONTENT_FORMATS } from "./constants.js";
4
+ const templateDraftSchema = z.object({
5
+ content: z.string().nullable(),
6
+ contentFormat: z.enum(CONTENT_FORMATS),
7
+ variableSchema: z.string(),
8
+ meta: z.string().nullable(),
9
+ title: z.string().nullable(),
10
+ folder: z.string().nullable(),
11
+ parentTemplateId: z.string().nullable(),
12
+ });
13
+ export function parseTemplateDraft(raw) {
14
+ if (raw === null)
15
+ return null;
16
+ try {
17
+ const parsed = templateDraftSchema.safeParse(JSON.parse(raw));
18
+ return parsed.success ? parsed.data : null;
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ export function serializeTemplateDraft(draft) {
25
+ return JSON.stringify(draft);
26
+ }
27
+ export function activeVersionOf(row) {
28
+ return row.activeVersion ?? row.version;
29
+ }
30
+ // `version` also counts draft saves, so only a row without a served version shows it as its number.
31
+ export function servedVersionOf(row) {
32
+ return row.status === "active" ? activeVersionOf(row) : row.version;
33
+ }
34
+ export function activeSinceOf(row) {
35
+ return row.activeSince ?? row.modifiedAt ?? row.insertedAt;
36
+ }
37
+ // A SystemAdmin edits system rows, so for them those rows count as their own.
38
+ function isSystemAdmin(user) {
39
+ return user.roles.includes("SystemAdmin");
40
+ }
41
+ // A system row that was never served keeps its draft in the main fields, so only a SystemAdmin may read it.
42
+ export function isHiddenSystemDraft(user, row) {
43
+ return row.scope === "system" && row.status === "draft" && !isSystemAdmin(user);
44
+ }
45
+ export function draftViewerTenantId(user, row) {
46
+ return row.scope === "system" && isSystemAdmin(user) ? row.tenantId : user.tenantId;
47
+ }
48
+ // The version an editor works on: the open draft if there is one, else the stored row.
49
+ // A draft is only shown to the tenant that owns the row, never through a system row.
50
+ export function toWorkingRow(row, viewerTenantId) {
51
+ const active = row.status === "active" ? { version: activeVersionOf(row), since: activeSinceOf(row) } : null;
52
+ const draft = row.tenantId === viewerTenantId ? parseTemplateDraft(row.draft) : null;
53
+ // Saves and discards of drafts raise row.version; an editor without a draft shows the served number.
54
+ if (draft === null)
55
+ return { ...row, version: active?.version ?? row.version, active };
56
+ return { ...row, ...draft, status: "draft", active };
57
+ }
58
+ // Event changes that turn a row into a served one. Every value is explicit so a
59
+ // rebuild reproduces the row without deriving anything.
60
+ export function servedStampChanges(row) {
61
+ return {
62
+ activeVersion: row === null ? 1 : row.version + 1,
63
+ activeSince: Temporal.Now.instant(),
64
+ };
65
+ }
66
+ export function activeStampChanges(row) {
67
+ return { status: "active", ...servedStampChanges(row) };
68
+ }
69
+ // Publishing also consumes the open draft.
70
+ export function activationChanges(row) {
71
+ return { ...activeStampChanges(row), draft: null };
72
+ }