@cosmicdrift/kumiko-samples 0.361.0 → 0.363.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 (265) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +17 -6
  3. package/packages/bundled-features/src/admin-shell/changes.json +6 -0
  4. package/packages/bundled-features/src/admin-shell/feature.ts +8 -1
  5. package/packages/bundled-features/src/agent-tools/agent-manifest.ts +3 -4
  6. package/packages/bundled-features/src/agent-tools/filter-ops.ts +1 -3
  7. package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -3
  8. package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +2 -1
  9. package/packages/bundled-features/src/auth-email-password/changes.json +14 -0
  10. package/packages/bundled-features/src/auth-email-password/email-templates.ts +12 -138
  11. package/packages/bundled-features/src/auth-email-password/feature.ts +30 -9
  12. package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +4 -5
  13. package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts +2 -5
  14. package/packages/bundled-features/src/auth-email-password/handlers/request-email-verification.write.ts +2 -5
  15. package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts +2 -5
  16. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +3 -4
  17. package/packages/bundled-features/src/auth-email-password/handlers/token-request-handler.ts +3 -12
  18. package/packages/bundled-features/src/auth-email-password/index.ts +2 -17
  19. package/packages/bundled-features/src/auth-email-password/magic-link-mail.ts +30 -22
  20. package/packages/bundled-features/src/auth-email-password/mail-notifications.ts +158 -0
  21. package/packages/bundled-features/src/auth-email-password/signup-activation.ts +2 -3
  22. package/packages/bundled-features/src/auth-foundation/types.ts +8 -18
  23. package/packages/bundled-features/src/auth-mfa/feature.ts +8 -10
  24. package/packages/bundled-features/src/auth-mfa/hmac-token-codec.ts +4 -4
  25. package/packages/bundled-features/src/auth-mfa/mfa-challenge-token.ts +3 -3
  26. package/packages/bundled-features/src/auth-mfa/mfa-preauth-setup-token.ts +3 -3
  27. package/packages/bundled-features/src/auth-mfa/mfa-setup-token.ts +8 -8
  28. package/packages/bundled-features/src/billing-foundation/changes.json +7 -0
  29. package/packages/bundled-features/src/billing-foundation/constants.ts +5 -4
  30. package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +38 -44
  31. package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +3 -3
  32. package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +115 -0
  33. package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +2 -0
  34. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-mail.ts +30 -30
  35. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-notify.ts +2 -2
  36. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +1 -4
  37. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +2 -2
  38. package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +2 -2
  39. package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +4 -9
  40. package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +1 -1
  41. package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +2 -2
  42. package/packages/bundled-features/src/billing-foundation/handlers/process-payment-event.write.ts +1 -1
  43. package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -6
  44. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +2 -1
  45. package/packages/bundled-features/src/cap-overview/web/cap-usage-cell.tsx +6 -4
  46. package/packages/bundled-features/src/channel-email/changes.json +19 -0
  47. package/packages/bundled-features/src/channel-email/email-channel.ts +122 -29
  48. package/packages/bundled-features/src/channel-email/feature.ts +6 -3
  49. package/packages/bundled-features/src/channel-email/index.ts +7 -1
  50. package/packages/bundled-features/src/channel-email/pii-guard.ts +13 -0
  51. package/packages/bundled-features/src/channel-email/smtp-transport.ts +15 -1
  52. package/packages/bundled-features/src/channel-email/types.ts +23 -0
  53. package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +2 -2
  54. package/packages/bundled-features/src/config/handlers/set.write.ts +1 -5
  55. package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +2 -2
  56. package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -11
  57. package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +7 -6
  58. package/packages/bundled-features/src/data-retention/changes.json +6 -0
  59. package/packages/bundled-features/src/data-retention/index.ts +1 -0
  60. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +8 -6
  61. package/packages/bundled-features/src/delivery/attachment-ref.ts +84 -0
  62. package/packages/bundled-features/src/delivery/changes.json +48 -0
  63. package/packages/bundled-features/src/delivery/channel-context.ts +129 -4
  64. package/packages/bundled-features/src/delivery/constants.ts +2 -0
  65. package/packages/bundled-features/src/delivery/delivery-service.ts +104 -26
  66. package/packages/bundled-features/src/delivery/feature.ts +1 -1
  67. package/packages/bundled-features/src/delivery/index.ts +17 -2
  68. package/packages/bundled-features/src/delivery/jobs.ts +48 -5
  69. package/packages/bundled-features/src/delivery/notify-factory.ts +14 -9
  70. package/packages/bundled-features/src/delivery/testing.ts +9 -1
  71. package/packages/bundled-features/src/delivery/types.ts +28 -18
  72. package/packages/bundled-features/src/delivery/unsubscribe.ts +5 -2
  73. package/packages/bundled-features/src/derivatives-sharp/render.ts +1 -22
  74. package/packages/bundled-features/src/document-ingest-foundation/aggregate-id.ts +10 -0
  75. package/packages/bundled-features/src/document-ingest-foundation/changes.json +6 -0
  76. package/packages/bundled-features/src/document-ingest-foundation/events.ts +3 -1
  77. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +5 -3
  78. package/packages/bundled-features/src/document-ingest-foundation/index.ts +1 -0
  79. package/packages/bundled-features/src/document-ingest-foundation/pages.ts +6 -3
  80. package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +4 -4
  81. package/packages/bundled-features/src/file-foundation/index.ts +7 -0
  82. package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +86 -0
  83. package/packages/bundled-features/src/folders/web/folder-manager.tsx +5 -2
  84. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +11 -11
  85. package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +2 -2
  86. package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +2 -2
  87. package/packages/bundled-features/src/form-draft/release-file-refs.ts +3 -2
  88. package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +1 -1
  89. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +6 -6
  90. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +1 -1
  91. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +1 -1
  92. package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +2 -2
  93. package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +7 -7
  94. package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +2 -6
  95. package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +5 -13
  96. package/packages/bundled-features/src/inbound-mail-foundation/types.ts +4 -6
  97. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +40 -25
  98. package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +4 -3
  99. package/packages/bundled-features/src/jobs/handlers/catalog.query.ts +1 -1
  100. package/packages/bundled-features/src/ledger/recurring.ts +1 -3
  101. package/packages/bundled-features/src/managed-pages/branding.ts +33 -9
  102. package/packages/bundled-features/src/managed-pages/changes.json +6 -0
  103. package/packages/bundled-features/src/managed-pages/feature.ts +1 -0
  104. package/packages/bundled-features/src/managed-pages/i18n.ts +1 -0
  105. package/packages/bundled-features/src/managed-pages/screens/branding-screen.ts +8 -0
  106. package/packages/bundled-features/src/page-render/branding.ts +3 -0
  107. package/packages/bundled-features/src/page-render/markdown.ts +1 -1
  108. package/packages/bundled-features/src/personal-access-tokens/feature.ts +2 -4
  109. package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +2 -1
  110. package/packages/bundled-features/src/personal-access-tokens/index.ts +1 -1
  111. package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +2 -1
  112. package/packages/bundled-features/src/renderer-foundation/README.md +11 -10
  113. package/packages/bundled-features/src/renderer-foundation/api.ts +14 -14
  114. package/packages/bundled-features/src/renderer-foundation/changes.json +39 -0
  115. package/packages/bundled-features/src/renderer-foundation/constants.ts +6 -8
  116. package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
  117. package/packages/bundled-features/src/renderer-foundation/index.ts +13 -2
  118. package/packages/bundled-features/src/renderer-foundation/types.ts +132 -35
  119. package/packages/bundled-features/src/renderer-pdf/feature.ts +7 -1
  120. package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +2 -2
  121. package/packages/bundled-features/src/sessions/feature.ts +2 -4
  122. package/packages/bundled-features/src/sessions/handlers/list.query.ts +2 -1
  123. package/packages/bundled-features/src/shared/attachment-file-name.ts +39 -0
  124. package/packages/bundled-features/src/shared/index.ts +6 -0
  125. package/packages/bundled-features/src/shared/is-tenant-db.ts +1 -1
  126. package/packages/bundled-features/src/shared/mail-template-body.ts +25 -0
  127. package/packages/bundled-features/src/shared/sharp-input-limits.ts +26 -0
  128. package/packages/bundled-features/src/shared/signup-handover.ts +4 -4
  129. package/packages/bundled-features/src/tags/handlers/assign-tag.write.ts +5 -1
  130. package/packages/bundled-features/src/tags/web/tag-chip.tsx +2 -1
  131. package/packages/bundled-features/src/template-resolver/README.md +63 -7
  132. package/packages/bundled-features/src/template-resolver/api.ts +83 -8
  133. package/packages/bundled-features/src/template-resolver/changes.json +118 -0
  134. package/packages/bundled-features/src/template-resolver/compile-document-body.ts +214 -0
  135. package/packages/bundled-features/src/template-resolver/constants.ts +39 -11
  136. package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +335 -0
  137. package/packages/bundled-features/src/template-resolver/document-schema.ts +323 -0
  138. package/packages/bundled-features/src/template-resolver/feature.ts +56 -6
  139. package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +188 -0
  140. package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +30 -2
  141. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +142 -0
  142. package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +72 -0
  143. package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +83 -0
  144. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +3 -3
  145. package/packages/bundled-features/src/template-resolver/handlers/import-bundle-system.write.ts +42 -0
  146. package/packages/bundled-features/src/template-resolver/handlers/import-bundle.write.ts +22 -0
  147. package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +108 -0
  148. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +5 -7
  149. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +250 -0
  150. package/packages/bundled-features/src/template-resolver/handlers/preview.query.ts +25 -0
  151. package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +58 -0
  152. package/packages/bundled-features/src/template-resolver/handlers/resource-link-pdf.write.ts +34 -0
  153. package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +50 -0
  154. package/packages/bundled-features/src/template-resolver/handlers/resource-shared.ts +24 -0
  155. package/packages/bundled-features/src/template-resolver/handlers/resource-upload.write.ts +135 -0
  156. package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +106 -0
  157. package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +32 -3
  158. package/packages/bundled-features/src/template-resolver/handlers/shared.ts +7 -2
  159. package/packages/bundled-features/src/template-resolver/handlers/template-gates.ts +184 -0
  160. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +183 -0
  161. package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +55 -0
  162. package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +57 -10
  163. package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +19 -71
  164. package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +15 -76
  165. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +17 -0
  166. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +116 -0
  167. package/packages/bundled-features/src/template-resolver/index.ts +100 -0
  168. package/packages/bundled-features/src/template-resolver/layout-regions.ts +206 -0
  169. package/packages/bundled-features/src/template-resolver/linked-resources.ts +102 -0
  170. package/packages/bundled-features/src/template-resolver/preview-display-html.ts +36 -0
  171. package/packages/bundled-features/src/template-resolver/print-document.ts +58 -0
  172. package/packages/bundled-features/src/template-resolver/qualified-names.ts +30 -0
  173. package/packages/bundled-features/src/template-resolver/record-mapping.ts +26 -0
  174. package/packages/bundled-features/src/template-resolver/resource-image.ts +47 -0
  175. package/packages/bundled-features/src/template-resolver/seeding.ts +147 -17
  176. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +416 -0
  177. package/packages/bundled-features/src/template-resolver/table.ts +14 -0
  178. package/packages/bundled-features/src/template-resolver/template-bundle.ts +79 -0
  179. package/packages/bundled-features/src/template-resolver/template-diff.ts +78 -0
  180. package/packages/bundled-features/src/template-resolver/template-meta.ts +129 -0
  181. package/packages/bundled-features/src/template-resolver/template-preview.ts +573 -0
  182. package/packages/bundled-features/src/template-resolver/template-resources.ts +74 -0
  183. package/packages/bundled-features/src/template-resolver/template-usage.ts +48 -0
  184. package/packages/bundled-features/src/template-resolver/template-validation.ts +229 -0
  185. package/packages/bundled-features/src/template-resolver/testing.ts +5 -5
  186. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +9 -6
  187. package/packages/bundled-features/src/template-resolver/web/document-editor-extensions.ts +162 -0
  188. package/packages/bundled-features/src/template-resolver/web/document-editor.tsx +28 -0
  189. package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +850 -0
  190. package/packages/bundled-features/src/template-resolver/web/document-toolbar-blocks.ts +61 -0
  191. package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +26 -0
  192. package/packages/bundled-features/src/template-resolver/web/i18n.ts +100 -0
  193. package/packages/bundled-features/src/template-resolver/web/index.ts +19 -0
  194. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor-lazy.tsx +36 -0
  195. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +169 -0
  196. package/packages/bundled-features/src/template-resolver/web/placeholder-text.ts +37 -0
  197. package/packages/bundled-features/src/template-resolver/web/use-stable-by-key.ts +14 -0
  198. package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +3 -2
  199. package/packages/bundled-features/src/tenant/seeding.ts +41 -7
  200. package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
  201. package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +2 -1
  202. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +4 -4
  203. package/packages/bundled-features/src/user/handlers/detail.query.ts +3 -5
  204. package/packages/bundled-features/src/user/roles-input-schema.ts +2 -2
  205. package/packages/bundled-features/src/user-data-rights/changes.json +14 -0
  206. package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +2 -2
  207. package/packages/bundled-features/src/user-data-rights/email-templates.ts +5 -149
  208. package/packages/bundled-features/src/user-data-rights/feature.ts +72 -35
  209. package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +2 -1
  210. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +5 -1
  211. package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +13 -1
  212. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +5 -11
  213. package/packages/bundled-features/src/user-data-rights/index.ts +1 -0
  214. package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +134 -53
  215. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +2 -2
  216. package/packages/bundled-features/src/user-data-rights/mail-notifications.ts +157 -0
  217. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +1 -1
  218. package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +6 -12
  219. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +2 -1
  220. package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +10 -1
  221. package/packages/bundled-features/src/user-data-rights-defaults/hooks/download-attempt.userdata-hook.ts +58 -0
  222. package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +2 -1
  223. package/packages/bundled-features/src/waitlist/changes.json +7 -0
  224. package/packages/bundled-features/src/waitlist/feature.ts +17 -0
  225. package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +4 -5
  226. package/packages/bundled-features/src/waitlist/mail.ts +69 -18
  227. package/packages/bundled-features/src/workflow-runner/event-trigger.ts +1 -2
  228. package/samples/apps/ui-walkthrough/package.json +2 -0
  229. package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +9 -0
  230. package/samples/apps/ui-walkthrough/src/app/client.tsx +6 -0
  231. package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +154 -0
  232. package/samples/apps/ui-walkthrough/src/app/server.ts +5 -1
  233. package/samples/apps/ui-walkthrough/src/app/shell.tsx +12 -1
  234. package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +354 -0
  235. package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +68 -0
  236. package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +18 -0
  237. package/samples/apps/ui-walkthrough/src/features/billing/index.ts +2 -0
  238. package/samples/apps/ui-walkthrough/src/features/billing/web/index.ts +7 -0
  239. package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +1 -1
  240. package/samples/apps/ui-walkthrough/src/run-config.ts +37 -1
  241. package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +0 -2
  242. package/samples/apps/use-all-bundled/feature-manifest.json +123 -22
  243. package/samples/apps/use-all-bundled/kumiko/migrations/0044_download-attempt-ip-bidx.rebuild.json +4 -0
  244. package/samples/apps/use-all-bundled/kumiko/migrations/0045_template-resource-meta.rebuild.json +4 -0
  245. package/samples/apps/use-all-bundled/kumiko/migrations/0046_pdf-rendered.rebuild.json +4 -0
  246. package/samples/apps/use-all-bundled/package.json +2 -0
  247. package/samples/apps/use-all-bundled/playwright.config.ts +38 -3
  248. package/samples/apps/use-all-bundled/schema/generate.ts +13 -3
  249. package/samples/apps/use-all-bundled/schema/schema.generated.ts +3 -0
  250. package/samples/apps/use-all-bundled/scripts/check-coverage.ts +3 -0
  251. package/samples/apps/use-all-bundled/src/app/auth-constants.ts +3 -0
  252. package/samples/apps/use-all-bundled/src/app/client.tsx +4 -0
  253. package/samples/apps/use-all-bundled/src/app/seed-documents.ts +128 -0
  254. package/samples/apps/use-all-bundled/src/app/seed.ts +4 -0
  255. package/samples/apps/use-all-bundled/src/run-config.ts +11 -11
  256. package/samples/recipes/delivery-notifications/README.md +26 -25
  257. package/samples/recipes/delivery-notifications/package.json +2 -1
  258. package/samples/recipes/delivery-notifications/src/feature.ts +64 -58
  259. package/samples/recipes/seed-migration/README.md +1 -1
  260. package/packages/bundled-features/src/renderer-simple/changes.json +0 -27
  261. package/packages/bundled-features/src/renderer-simple/feature.ts +0 -66
  262. package/packages/bundled-features/src/renderer-simple/index.ts +0 -8
  263. package/packages/bundled-features/src/renderer-simple/mail-blocks.ts +0 -138
  264. package/packages/bundled-features/src/renderer-simple/resolve-variables.ts +0 -57
  265. package/packages/bundled-features/src/renderer-simple/simple-renderer.ts +0 -304
@@ -10,10 +10,10 @@ import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
10
10
  import { WAITLIST_NOTIFICATION_TYPES, WAITLIST_STATUS } from "../constants.js";
11
11
  import { normalizeEmail, platformActor, waitlistDb, waitlistExecutor } from "../lib.js";
12
12
  import {
13
- renderWaitlistAdminNoticeEmail,
14
- renderWaitlistConfirmationEmail,
15
13
  resolveWaitlistAdminMailLocale,
16
14
  resolveWaitlistMailLocale,
15
+ waitlistAdminNoticeVariables,
16
+ waitlistConfirmationVariables,
17
17
  } from "../mail.js";
18
18
  import {
19
19
  DEFAULT_SUBMIT_EMAIL_RATE_LIMITS,
@@ -130,7 +130,7 @@ export function createSubmitHandler(opts: WaitlistOptions) {
130
130
  await sendBestEffort(ctx, "confirmation", (notify) =>
131
131
  notify(WAITLIST_NOTIFICATION_TYPES.confirmation, {
132
132
  route: { email },
133
- data: renderWaitlistConfirmationEmail({
133
+ data: waitlistConfirmationVariables({
134
134
  locale: payload.locale,
135
135
  appName: opts.appName,
136
136
  }),
@@ -145,12 +145,11 @@ export function createSubmitHandler(opts: WaitlistOptions) {
145
145
  if (!adminRecipient) return;
146
146
  await notify(WAITLIST_NOTIFICATION_TYPES.adminNotice, {
147
147
  route: { email: adminRecipient },
148
- data: renderWaitlistAdminNoticeEmail({
148
+ data: waitlistAdminNoticeVariables({
149
149
  name: payload.name,
150
150
  email,
151
151
  company: payload.company,
152
152
  message: payload.message,
153
- adminLocale: ctx.locale,
154
153
  }),
155
154
  priority: "normal",
156
155
  locale: resolveWaitlistAdminMailLocale(ctx.locale),
@@ -1,4 +1,10 @@
1
- import type { AuthMailContent } from "../auth-email-password/index.js";
1
+ import {
2
+ type NotificationLocalizedTemplate,
3
+ type NotificationRecordMapping,
4
+ type TemplateVariables,
5
+ templateVariable,
6
+ } from "@cosmicdrift/kumiko-framework/engine";
7
+ import { mailHeading, mailParagraph, mailRepeatedRows } from "../shared/index.js";
2
8
 
3
9
  export type WaitlistMailLocale = "en" | "de" | "es";
4
10
 
@@ -72,43 +78,88 @@ export function resolveWaitlistMailLocale(locale: string | undefined): WaitlistM
72
78
  return isConfirmationLocale(language) ? language : "en";
73
79
  }
74
80
 
81
+ export const WAITLIST_CONFIRMATION_VARIABLES: TemplateVariables = {
82
+ subject: templateVariable.text({ required: true }),
83
+ intro: templateVariable.text({ required: true }),
84
+ footer: templateVariable.text({ required: true }),
85
+ };
86
+
87
+ // Only `name` is a plain entry field; the details rows are composed from several fields.
88
+ export const WAITLIST_ADMIN_NOTICE_RECORD: NotificationRecordMapping = {
89
+ entity: "waitlistEntry",
90
+ map: { name: "name" },
91
+ };
92
+
93
+ export const WAITLIST_ADMIN_NOTICE_VARIABLES: TemplateVariables = {
94
+ name: templateVariable.text({ required: true }),
95
+ details: templateVariable.list(
96
+ { text: templateVariable.text({ required: true }) },
97
+ { required: true },
98
+ ),
99
+ };
100
+
101
+ // The app name is optional, so the sentences that mention it are computed in
102
+ // code and handed over as variables; the template keeps heading and structure.
75
103
  // The submitter's name stays out: the address is unverified, so any text in
76
104
  // this mail could be planted by whoever typed someone else's email.
77
- export function renderWaitlistConfirmationEmail(args: {
105
+ export function waitlistConfirmationVariables(args: {
78
106
  readonly locale: string | undefined;
79
107
  readonly appName?: string | undefined;
80
- }): AuthMailContent {
108
+ }): { readonly subject: string; readonly intro: string; readonly footer: string } {
81
109
  const t = CONFIRMATION_STRINGS[resolveWaitlistMailLocale(args.locale)];
82
110
  return {
83
111
  subject: t.subject(args.appName),
84
- header: t.header,
85
- sections: [{ text: t.intro(args.appName) }],
112
+ intro: t.intro(args.appName),
86
113
  footer: t.footer(args.appName),
87
114
  };
88
115
  }
89
116
 
117
+ export function waitlistConfirmationTemplate(): NotificationLocalizedTemplate {
118
+ return Object.fromEntries(
119
+ Object.entries(CONFIRMATION_STRINGS).map(([locale, t]) => [
120
+ locale,
121
+ {
122
+ body: [mailHeading(t.header), mailParagraph("{intro}"), mailParagraph("{footer}")].join(""),
123
+ meta: { subject: "{{subject}}", category: "transactional" as const },
124
+ },
125
+ ]),
126
+ );
127
+ }
128
+
90
129
  // Operator-facing, so the entrant's locale does not apply: en/de, en default.
91
130
  export function resolveWaitlistAdminMailLocale(adminLocale: string | undefined): "en" | "de" {
92
131
  return languageOf(adminLocale) === "de" ? "de" : "en";
93
132
  }
94
133
 
95
- export function renderWaitlistAdminNoticeEmail(args: {
134
+ export function waitlistAdminNoticeVariables(args: {
96
135
  readonly name: string;
97
136
  readonly email: string;
98
137
  readonly company: string | undefined;
99
138
  readonly message: string | undefined;
100
- readonly adminLocale: string | undefined;
101
- }): AuthMailContent {
102
- const t = ADMIN_NOTICE_STRINGS[resolveWaitlistAdminMailLocale(args.adminLocale)];
103
- const details = [
104
- `${args.name} <${args.email}>`,
105
- ...(args.company ? [args.company] : []),
106
- ...(args.message ? [args.message] : []),
107
- ];
139
+ }): { readonly name: string; readonly details: readonly { readonly text: string }[] } {
108
140
  return {
109
- subject: t.subject(args.name),
110
- header: t.header,
111
- sections: [{ text: t.intro }, { text: details.join("\n") }],
112
- footer: t.footer,
141
+ name: args.name,
142
+ details: [
143
+ `${args.name} <${args.email}>`,
144
+ ...(args.company ? [args.company] : []),
145
+ ...(args.message ? [args.message] : []),
146
+ ].map((text) => ({ text })),
113
147
  };
114
148
  }
149
+
150
+ export function waitlistAdminNoticeTemplate(): NotificationLocalizedTemplate {
151
+ return Object.fromEntries(
152
+ Object.entries(ADMIN_NOTICE_STRINGS).map(([locale, t]) => [
153
+ locale,
154
+ {
155
+ body: [
156
+ mailHeading(t.header),
157
+ mailParagraph(t.intro),
158
+ mailRepeatedRows("details", "text"),
159
+ mailParagraph(t.footer),
160
+ ].join(""),
161
+ meta: { subject: t.subject("{{name}}"), category: "transactional" as const },
162
+ },
163
+ ]),
164
+ );
165
+ }
@@ -22,7 +22,6 @@ import {
22
22
  describeWorkflowStepError,
23
23
  getStep,
24
24
  SYSTEM_TENANT_ID,
25
- type TenantId,
26
25
  WORKFLOW_AGGREGATE_TYPE,
27
26
  WORKFLOW_RUN_FAILED_TYPE,
28
27
  WorkflowStepError,
@@ -71,7 +70,7 @@ export function assertEventTriggerStepsSupported(workflow: WorkflowDefinition):
71
70
  steps = buildPipelineSteps(workflow.pipelineDef, {
72
71
  type: "workflow-registration-probe",
73
72
  payload: {},
74
- user: createSystemUser(SYSTEM_TENANT_ID as TenantId),
73
+ user: createSystemUser(SYSTEM_TENANT_ID),
75
74
  });
76
75
  } catch (error) {
77
76
  throw new Error(
@@ -10,9 +10,11 @@
10
10
  "dependencies": {
11
11
  "@cosmicdrift/kumiko-bundled-features": "workspace:*",
12
12
  "@cosmicdrift/kumiko-dev-server": "workspace:*",
13
+ "@cosmicdrift/kumiko-document-designer": "workspace:*",
13
14
  "@cosmicdrift/kumiko-dispatcher-live": "workspace:*",
14
15
  "@cosmicdrift/kumiko-framework": "workspace:*",
15
16
  "@cosmicdrift/kumiko-headless": "workspace:*",
17
+ "@cosmicdrift/kumiko-renderer-mail-html": "workspace:*",
16
18
  "@cosmicdrift/kumiko-renderer-web": "workspace:*",
17
19
  "@cosmicdrift/kumiko-server-runtime": "workspace:*",
18
20
  "react": "^19.2.6",
@@ -18,3 +18,12 @@ export const ADMIN_PASSWORD = "kumiko-admin";
18
18
  // `as TenantId`-Cast lokal.
19
19
  export const DEV_TENANT_ID = "00000000-0000-4000-8000-000000000001";
20
20
  export const BETA_TENANT_ID = "00000000-0000-4000-8000-000000000002";
21
+
22
+ // Nordlicht Immobilien GmbH: the tenant the document-designer walkthrough runs
23
+ // in. Both users are new; the admin above stays untouched.
24
+ export const NORDLICHT_TENANT_ID = "00000000-0000-4000-8000-000000000003";
25
+ export const NORDLICHT_TENANT_NAME = "Nordlicht Immobilien GmbH";
26
+ export const TENANT_ADMIN_EMAIL = "a.berger@nordlicht-immobilien.de";
27
+ export const TENANT_ADMIN_PASSWORD = "nordlicht-berger";
28
+ export const PLATFORM_ADMIN_EMAIL = "plattform@kumiko.dev";
29
+ export const PLATFORM_ADMIN_PASSWORD = "kumiko-plattform";
@@ -2,8 +2,11 @@
2
2
  // übergibt Shell + clientFeatures an createKumikoApp.
3
3
 
4
4
  import { emailPasswordClient } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/web";
5
+ import { textBlocksClient } from "@cosmicdrift/kumiko-bundled-features/template-resolver/web";
6
+ import { documentDesignerClient } from "@cosmicdrift/kumiko-document-designer/web";
5
7
  import { localeDeClient } from "@cosmicdrift/kumiko-locale-de/web";
6
8
  import { createKumikoApp } from "@cosmicdrift/kumiko-renderer-web";
9
+ import { billingClient } from "../features/billing/web";
7
10
  import { rentalClient } from "../features/rental/web";
8
11
  import { tasksClient } from "../features/tasks/web";
9
12
  import { vehiclesClient } from "../features/vehicles/web";
@@ -17,5 +20,8 @@ createKumikoApp({
17
20
  tasksClient,
18
21
  rentalClient,
19
22
  vehiclesClient,
23
+ billingClient,
24
+ textBlocksClient(),
25
+ documentDesignerClient(),
20
26
  ],
21
27
  });
@@ -0,0 +1,154 @@
1
+ // Nordlicht Immobilien GmbH for the document-designer walkthrough: a tenant
2
+ // admin, a platform admin, branding and a realistic set of mail and PDF
3
+ // templates. Everything goes through the template write handlers (or the
4
+ // system-template seed), never straight into the tables.
5
+
6
+ import { seedAdmin } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/seeding";
7
+ import { BRANDING_QN } from "@cosmicdrift/kumiko-bundled-features/managed-pages";
8
+ import {
9
+ TemplateResolverHandlers,
10
+ TemplateResolverQueries,
11
+ } from "@cosmicdrift/kumiko-bundled-features/template-resolver";
12
+ import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
13
+ import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
14
+ import { DEFAULT_MAIL_LAYOUT_MJML } from "@cosmicdrift/kumiko-renderer-mail-html";
15
+ import {
16
+ NORDLICHT_TENANT_ID,
17
+ NORDLICHT_TENANT_NAME,
18
+ PLATFORM_ADMIN_EMAIL,
19
+ PLATFORM_ADMIN_PASSWORD,
20
+ TENANT_ADMIN_EMAIL,
21
+ TENANT_ADMIN_PASSWORD,
22
+ } from "./auth-constants";
23
+ import {
24
+ INVOICE_CORRECTED_DRAFT,
25
+ INVOICE_ISSUED_DRAFT_VERSIONS,
26
+ PAYMENT_REMINDER_TEMPLATES,
27
+ type SeedTemplate,
28
+ SYSTEM_AUTH_MAILS,
29
+ SYSTEM_INVOICE_DOCUMENTS,
30
+ SYSTEM_INVOICE_ISSUED,
31
+ SYSTEM_PDF_LAYOUT,
32
+ SYSTEM_TENANCY_CERTIFICATE,
33
+ TENANT_MAIL_LAYOUT_VERSIONS,
34
+ TENANT_UTILITY_STATEMENT,
35
+ } from "./template-seed-data";
36
+
37
+ const NORDLICHT = NORDLICHT_TENANT_ID as TenantId;
38
+
39
+ const BRANDING = [
40
+ [BRANDING_QN.title, "Nordlicht Mieterportal"],
41
+ [BRANDING_QN.accentColor, "#205265"],
42
+ [BRANDING_QN.siteUrl, "https://nordlicht-immobilien.de"],
43
+ [BRANDING_QN.logoUrl, "https://nordlicht-immobilien.de/logo-nordlicht.png"],
44
+ ] as const;
45
+
46
+ export const seedTemplates: SeedFn = async (stack) => {
47
+ const membership = (roles: readonly string[]) => [
48
+ {
49
+ tenantId: NORDLICHT,
50
+ tenantKey: "nordlicht",
51
+ tenantName: NORDLICHT_TENANT_NAME,
52
+ roles,
53
+ },
54
+ ];
55
+ const tenantAdminAccount = await seedAdmin(stack.db, {
56
+ email: TENANT_ADMIN_EMAIL,
57
+ password: TENANT_ADMIN_PASSWORD,
58
+ displayName: "A. Berger",
59
+ emailVerified: true,
60
+ memberships: membership(["TenantAdmin"]),
61
+ });
62
+ const platformAdminAccount = await seedAdmin(stack.db, {
63
+ email: PLATFORM_ADMIN_EMAIL,
64
+ password: PLATFORM_ADMIN_PASSWORD,
65
+ displayName: "Plattform-Admin",
66
+ emailVerified: true,
67
+ globalRoles: ["SystemAdmin"],
68
+ memberships: membership(["TenantAdmin"]),
69
+ });
70
+ // The session re-derives roles from the membership row on every request, so
71
+ // the roles here only have to match what the account really has.
72
+ const tenantAdmin: SessionUser = {
73
+ id: tenantAdminAccount.id as SessionUser["id"],
74
+ tenantId: NORDLICHT,
75
+ roles: ["TenantAdmin"],
76
+ };
77
+ const platformAdmin: SessionUser = {
78
+ id: platformAdminAccount.id as SessionUser["id"],
79
+ tenantId: NORDLICHT,
80
+ roles: ["TenantAdmin", "SystemAdmin"],
81
+ };
82
+
83
+ const overview = await stack.http.queryOk<{ rows: { origin: string }[] }>(
84
+ TemplateResolverQueries.overview,
85
+ {},
86
+ tenantAdmin,
87
+ );
88
+ if (overview.rows.some((row) => row.origin === "tenant")) return;
89
+
90
+ const upsert = (
91
+ handler: string,
92
+ template: SeedTemplate,
93
+ user: SessionUser,
94
+ extra: Record<string, unknown> = {},
95
+ ) =>
96
+ stack.http.writeOk<{ id: string }>(
97
+ handler,
98
+ {
99
+ slug: template.slug,
100
+ kind: template.kind,
101
+ locale: template.locale,
102
+ contentFormat: "html",
103
+ content: template.content,
104
+ ...(template.title !== undefined && { title: template.title }),
105
+ ...(template.meta !== undefined && { meta: template.meta }),
106
+ ...(template.variableSchema !== undefined && { variableSchema: template.variableSchema }),
107
+ ...extra,
108
+ },
109
+ user,
110
+ );
111
+ const upsertSystem = (template: SeedTemplate) =>
112
+ upsert(TemplateResolverHandlers.upsertSystem, template, platformAdmin);
113
+ const upsertTenant = (template: SeedTemplate, status: "draft" | "active") =>
114
+ upsert(TemplateResolverHandlers.upsertTenant, template, tenantAdmin, { status });
115
+
116
+ await stack.http.writeOk(
117
+ TemplateResolverHandlers.upsertSystem,
118
+ {
119
+ slug: "default",
120
+ kind: "mail-layout",
121
+ locale: "en",
122
+ contentFormat: "mjml",
123
+ content: DEFAULT_MAIL_LAYOUT_MJML,
124
+ title: "Mail-Layout",
125
+ },
126
+ platformAdmin,
127
+ );
128
+ await upsertSystem(SYSTEM_PDF_LAYOUT);
129
+ for (const mail of SYSTEM_AUTH_MAILS) await upsertSystem(mail);
130
+ await upsertSystem(SYSTEM_INVOICE_ISSUED);
131
+ for (const document of SYSTEM_INVOICE_DOCUMENTS) await upsertSystem(document);
132
+ const certificate = await upsertSystem(SYSTEM_TENANCY_CERTIFICATE);
133
+ await stack.http.writeOk(
134
+ TemplateResolverHandlers.archiveSystem,
135
+ { id: certificate.id },
136
+ platformAdmin,
137
+ );
138
+
139
+ for (const [key, value] of BRANDING) {
140
+ await stack.http.writeOk("config:write:set", { key, value }, tenantAdmin);
141
+ }
142
+ // Each save is a new version of the same row; the second one makes the
143
+ // layout "customised" for the overview and the first leaves history to diff.
144
+ for (const content of TENANT_MAIL_LAYOUT_VERSIONS) {
145
+ await upsertTenant(
146
+ { slug: "default", kind: "mail-layout", locale: "en", title: "Mail-Layout", content },
147
+ "active",
148
+ );
149
+ }
150
+ for (const draft of INVOICE_ISSUED_DRAFT_VERSIONS) await upsertTenant(draft, "draft");
151
+ await upsertTenant(INVOICE_CORRECTED_DRAFT, "draft");
152
+ for (const reminder of PAYMENT_REMINDER_TEMPLATES) await upsertTenant(reminder, "active");
153
+ await upsertTenant(TENANT_UTILITY_STATEMENT, "active");
154
+ };
@@ -11,10 +11,12 @@
11
11
 
12
12
  import { runDevApp } from "@cosmicdrift/kumiko-dev-server";
13
13
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
14
+ import { createInMemoryFileProvider } from "@cosmicdrift/kumiko-framework/files";
14
15
  import { APP_FEATURES } from "../run-config";
15
16
  import { ADMIN_EMAIL, ADMIN_PASSWORD, BETA_TENANT_ID, DEV_TENANT_ID } from "./auth-constants";
16
17
  import { seedTasks } from "./seed";
17
18
  import { seedRental } from "./seed-rental";
19
+ import { seedTemplates } from "./seed-templates";
18
20
  import { seedVehicles } from "./seed-vehicles";
19
21
 
20
22
  // Zwei feste Tenants — Admin ist in beiden Mitglied damit der
@@ -25,10 +27,12 @@ import { seedVehicles } from "./seed-vehicles";
25
27
 
26
28
  await runDevApp({
27
29
  features: [...APP_FEATURES],
28
- seeds: [seedTasks, seedRental, seedVehicles],
30
+ seeds: [seedTasks, seedRental, seedVehicles, seedTemplates],
29
31
  // PORT env-var override für Playwright-e2e-Runs (config zeigt auf 4174);
30
32
  // sonst lokal-Default 4173.
31
33
  port: Number.parseInt(process.env["PORT"] ?? "4173", 10),
34
+ // Logo and attachment uploads of the mail editor need a file store.
35
+ files: { storageProvider: createInMemoryFileProvider() },
32
36
  clientEntry: "./src/app/client.tsx",
33
37
  htmlPath: "./public/index.html",
34
38
  watchDirs: ["./src", "../../../packages/*/src"],
@@ -5,6 +5,7 @@
5
5
  import {
6
6
  TenantMenuItems,
7
7
  UserMenu,
8
+ useSession,
8
9
  } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/web";
9
10
  import {
10
11
  type AppSchema,
@@ -18,13 +19,19 @@ import {
18
19
  import { MoonStar, Sun } from "lucide-react";
19
20
  import type { ReactNode } from "react";
20
21
  import { AssistantAction } from "./assistant-action";
21
- import { BETA_TENANT_ID, DEV_TENANT_ID } from "./auth-constants";
22
+ import {
23
+ BETA_TENANT_ID,
24
+ DEV_TENANT_ID,
25
+ NORDLICHT_TENANT_ID,
26
+ NORDLICHT_TENANT_NAME,
27
+ } from "./auth-constants";
22
28
 
23
29
  const APP_NAME = "Kumiko Walkthrough";
24
30
 
25
31
  const tenantName = (tenantId: string): string => {
26
32
  if (tenantId === DEV_TENANT_ID) return "Dev Tenant";
27
33
  if (tenantId === BETA_TENANT_ID) return "Beta Tenant";
34
+ if (tenantId === NORDLICHT_TENANT_ID) return NORDLICHT_TENANT_NAME;
28
35
  return tenantId.slice(0, 8);
29
36
  };
30
37
 
@@ -41,10 +48,14 @@ export function AppShell({
41
48
  readonly schema: AppSchema;
42
49
  }): ReactNode {
43
50
  const t = useTranslation();
51
+ const session = useSession();
52
+ // Without the user the shell hides role-gated navs and KumikoScreen denies role-gated screens.
53
+ const user = session.user !== null ? { id: session.user.id, roles: session.roles } : undefined;
44
54
  return (
45
55
  <DefaultAppShell
46
56
  brand={<SidebarBrand name={APP_NAME} plan={t("tasks.shell.tagline")} />}
47
57
  schema={schema}
58
+ {...(user !== undefined && { user })}
48
59
  headerActions={
49
60
  <>
50
61
  <AssistantAction />