@cosmicdrift/kumiko-samples 0.374.0 → 0.378.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 (247) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +6 -4
  3. package/packages/bundled-features/src/account-security/changes.json +6 -0
  4. package/packages/bundled-features/src/account-security/constants.ts +1 -0
  5. package/packages/bundled-features/src/account-security/index.ts +1 -0
  6. package/packages/bundled-features/src/admin-shell/web/client-plugin.tsx +1 -1
  7. package/packages/bundled-features/src/audit/web/client-plugin.tsx +1 -1
  8. package/packages/bundled-features/src/auth-email-password/mail-notifications.ts +1 -1
  9. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +1 -1
  10. package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +1 -1
  11. package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +3 -3
  12. package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +1 -1
  13. package/packages/bundled-features/src/auth-email-password/web/index.ts +1 -1
  14. package/packages/bundled-features/src/auth-email-password/web/session.tsx +1 -1
  15. package/packages/bundled-features/src/auth-email-password/web/tenant-menu-items.tsx +1 -1
  16. package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +1 -1
  17. package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +1 -1
  18. package/packages/bundled-features/src/auth-foundation/changes.json +6 -0
  19. package/packages/bundled-features/src/auth-foundation/env.ts +27 -0
  20. package/packages/bundled-features/src/auth-foundation/index.ts +1 -0
  21. package/packages/bundled-features/src/billing-foundation/changes.json +6 -0
  22. package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +1 -1
  23. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +1 -1
  24. package/packages/bundled-features/src/billing-foundation/contact-card.ts +14 -0
  25. package/packages/bundled-features/src/billing-foundation/handlers/billing-plans.query.ts +1 -1
  26. package/packages/bundled-features/src/billing-foundation/index.ts +1 -0
  27. package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +1 -0
  28. package/packages/bundled-features/src/billing-foundation/types.ts +12 -0
  29. package/packages/bundled-features/src/billing-foundation/validate-options.ts +16 -0
  30. package/packages/bundled-features/src/billing-foundation/web/billing-contact-plan.tsx +32 -0
  31. package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +5 -15
  32. package/packages/bundled-features/src/billing-foundation/web/cancel-contract-dialog.tsx +2 -2
  33. package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +1 -1
  34. package/packages/bundled-features/src/billing-foundation/web/client-plugin.tsx +1 -1
  35. package/packages/bundled-features/src/billing-foundation/web/localized-params.ts +14 -0
  36. package/packages/bundled-features/src/cap-counter/changes.json +12 -0
  37. package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +9 -0
  38. package/packages/bundled-features/src/cap-overview/web/cap-cards-panel.tsx +3 -3
  39. package/packages/bundled-features/src/cap-overview/web/client-plugin.tsx +1 -1
  40. package/packages/bundled-features/src/channel-email/changes.json +6 -0
  41. package/packages/bundled-features/src/channel-email/email-channel.ts +2 -1
  42. package/packages/bundled-features/src/compliance-profiles/web/client-plugin.tsx +1 -1
  43. package/packages/bundled-features/src/config/feature.ts +2 -2
  44. package/packages/bundled-features/src/config/web/i18n.ts +1 -0
  45. package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
  46. package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +1 -1
  47. package/packages/bundled-features/src/delivery/unsubscribe-page.ts +1 -1
  48. package/packages/bundled-features/src/delivery/web/client-plugin.tsx +1 -1
  49. package/packages/bundled-features/src/delivery/web/delivery-status-cell.tsx +1 -1
  50. package/packages/bundled-features/src/feature-toggles/web/client-plugin.tsx +1 -1
  51. package/packages/bundled-features/src/file-provider-s3/changes.json +6 -0
  52. package/packages/bundled-features/src/file-provider-s3/env-named-feature.ts +45 -0
  53. package/packages/bundled-features/src/file-provider-s3/env-schema.ts +20 -13
  54. package/packages/bundled-features/src/file-provider-s3/index.ts +4 -0
  55. package/packages/bundled-features/src/folders/web/client-plugin.tsx +1 -1
  56. package/packages/bundled-features/src/folders/web/folder-section.tsx +3 -4
  57. package/packages/bundled-features/src/host-routing/README.md +7 -0
  58. package/packages/bundled-features/src/host-routing/changes.json +6 -0
  59. package/packages/bundled-features/src/host-routing/constants.ts +4 -0
  60. package/packages/bundled-features/src/host-routing/dispatch.ts +34 -26
  61. package/packages/bundled-features/src/host-routing/feature.ts +122 -41
  62. package/packages/bundled-features/src/host-routing/host.ts +28 -1
  63. package/packages/bundled-features/src/host-routing/index.ts +3 -0
  64. package/packages/bundled-features/src/host-routing/options.ts +45 -2
  65. package/packages/bundled-features/src/host-routing/redirects.ts +33 -0
  66. package/packages/bundled-features/src/host-routing/tenant-lookup.ts +65 -0
  67. package/packages/bundled-features/src/host-routing/validate-options.ts +48 -1
  68. package/packages/bundled-features/src/inbound-mail-foundation/changes.json +13 -0
  69. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +8 -0
  70. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +11 -4
  71. package/packages/bundled-features/src/inbound-mail-foundation/i18n.ts +42 -0
  72. package/packages/bundled-features/src/inbound-mail-foundation/index.ts +4 -0
  73. package/packages/bundled-features/src/inbound-mail-foundation/screens.ts +100 -0
  74. package/packages/bundled-features/src/inbound-mail-foundation/types.ts +2 -2
  75. package/packages/bundled-features/src/jobs/web/client-plugin.tsx +1 -1
  76. package/packages/bundled-features/src/legal-pages/changes.json +6 -0
  77. package/packages/bundled-features/src/legal-pages/feature.ts +14 -1
  78. package/packages/bundled-features/src/legal-pages/layout.ts +6 -6
  79. package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +1 -1
  80. package/packages/bundled-features/src/mail-foundation/changes.json +6 -0
  81. package/packages/bundled-features/src/mail-foundation/feature.ts +21 -22
  82. package/packages/bundled-features/src/mail-foundation/i18n.ts +3 -2
  83. package/packages/bundled-features/src/mail-transport-smtp/i18n.ts +1 -1
  84. package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +1 -1
  85. package/packages/bundled-features/src/notes-history/web/client-plugin.tsx +1 -1
  86. package/packages/bundled-features/src/page-render/branding.ts +1 -1
  87. package/packages/bundled-features/src/page-render/layout.ts +2 -2
  88. package/packages/bundled-features/src/page-render/markdown.ts +1 -1
  89. package/packages/bundled-features/src/personal-access-tokens/i18n.ts +1 -1
  90. package/packages/bundled-features/src/personal-access-tokens/screens.ts +1 -1
  91. package/packages/bundled-features/src/secrets/feature.ts +4 -4
  92. package/packages/bundled-features/src/seo/sitemap.ts +1 -1
  93. package/packages/bundled-features/src/shared/mail-template-body.ts +1 -1
  94. package/packages/bundled-features/src/shared/purge-files-reaching-subject.ts +127 -2
  95. package/packages/bundled-features/src/tags/web/client-plugin.tsx +1 -1
  96. package/packages/bundled-features/src/template-resolver/changes.json +38 -0
  97. package/packages/bundled-features/src/template-resolver/compile-document-body.ts +61 -3
  98. package/packages/bundled-features/src/template-resolver/constants.ts +3 -0
  99. package/packages/bundled-features/src/template-resolver/document-blocks.ts +36 -0
  100. package/packages/bundled-features/src/template-resolver/document-images.ts +29 -0
  101. package/packages/bundled-features/src/template-resolver/document-ops.ts +515 -0
  102. package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +44 -0
  103. package/packages/bundled-features/src/template-resolver/document-schema.ts +5 -0
  104. package/packages/bundled-features/src/template-resolver/feature.ts +79 -34
  105. package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +1 -0
  106. package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
  107. package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -1
  108. package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +2 -6
  109. package/packages/bundled-features/src/template-resolver/handlers/collection-shared.ts +0 -6
  110. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +67 -58
  111. package/packages/bundled-features/src/template-resolver/handlers/discard-draft.write.ts +36 -13
  112. package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +86 -0
  113. package/packages/bundled-features/src/template-resolver/handlers/document-blocks.query.ts +48 -0
  114. package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +11 -3
  115. package/packages/bundled-features/src/template-resolver/handlers/import-bundle.write.ts +37 -28
  116. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +66 -62
  117. package/packages/bundled-features/src/template-resolver/handlers/patch-draft.write.ts +134 -0
  118. package/packages/bundled-features/src/template-resolver/handlers/preview.query.ts +2 -1
  119. package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +62 -49
  120. package/packages/bundled-features/src/template-resolver/handlers/resource-link-pdf.write.ts +44 -29
  121. package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +52 -36
  122. package/packages/bundled-features/src/template-resolver/handlers/resource-upload.write.ts +126 -106
  123. package/packages/bundled-features/src/template-resolver/handlers/send-test-shared.ts +38 -0
  124. package/packages/bundled-features/src/template-resolver/handlers/send-test-status.query.ts +31 -0
  125. package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +105 -110
  126. package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +110 -103
  127. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +22 -1
  128. package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +56 -28
  129. package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +38 -29
  130. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +24 -9
  131. package/packages/bundled-features/src/template-resolver/index.ts +8 -1
  132. package/packages/bundled-features/src/template-resolver/{web/placeholder-text.ts → placeholder-text.ts} +1 -1
  133. package/packages/bundled-features/src/template-resolver/qualified-names.ts +4 -0
  134. package/packages/bundled-features/src/template-resolver/seeding.ts +3 -1
  135. package/packages/bundled-features/src/template-resolver/template-bundle.ts +6 -1
  136. package/packages/bundled-features/src/template-resolver/template-edit-policy.ts +91 -0
  137. package/packages/bundled-features/src/template-resolver/template-preview.ts +32 -10
  138. package/packages/bundled-features/src/template-resolver/template-validation.ts +32 -11
  139. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +3 -3
  140. package/packages/bundled-features/src/template-resolver/web/document-editor-extensions.ts +29 -0
  141. package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +43 -5
  142. package/packages/bundled-features/src/template-resolver/web/document-toolbar-blocks.ts +9 -33
  143. package/packages/bundled-features/src/template-resolver/web/i18n.ts +30 -0
  144. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +2 -2
  145. package/packages/bundled-features/src/tenant/web/client-plugin.tsx +1 -1
  146. package/packages/bundled-features/src/tenant/web/member-status-cell.tsx +1 -1
  147. package/packages/bundled-features/src/tier-engine/web/client-plugin.tsx +1 -1
  148. package/packages/bundled-features/src/user-data-rights/changes.json +6 -0
  149. package/packages/bundled-features/src/user-data-rights/env.ts +15 -0
  150. package/packages/bundled-features/src/user-data-rights/feature.ts +4 -2
  151. package/packages/bundled-features/src/user-data-rights/index.ts +1 -0
  152. package/packages/bundled-features/src/user-data-rights/lib/mail-transport-resolver.ts +1 -1
  153. package/packages/bundled-features/src/user-data-rights/lib/storage-provider-resolver.ts +1 -1
  154. package/packages/bundled-features/src/user-data-rights/mail-notifications.ts +1 -1
  155. package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +1 -1
  156. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +2 -2
  157. package/packages/bundled-features/src/waitlist/changes.json +6 -0
  158. package/packages/bundled-features/src/waitlist/legacy-migrate.ts +51 -2
  159. package/samples/apps/admin-console/package.json +0 -3
  160. package/samples/apps/admin-console/src/app/client.tsx +1 -1
  161. package/samples/apps/admin-console/src/app/shell.tsx +1 -1
  162. package/samples/apps/config-demo/package.json +1 -3
  163. package/samples/apps/config-demo/src/app/client.tsx +1 -1
  164. package/samples/apps/config-demo/src/app/shell.tsx +2 -2
  165. package/samples/apps/config-demo/src/features/demo/web/index.ts +1 -1
  166. package/samples/apps/config-demo/tsconfig.json +0 -12
  167. package/samples/apps/marketing-demo/package.json +1 -3
  168. package/samples/apps/marketing-demo/src/app/client.tsx +1 -1
  169. package/samples/apps/marketing-demo/src/app/shell.tsx +1 -1
  170. package/samples/apps/marketing-demo/src/features/assets/web/index.ts +1 -1
  171. package/samples/apps/marketing-demo/src/features/helpdesk/web/index.ts +1 -1
  172. package/samples/apps/showcase/package.json +1 -3
  173. package/samples/apps/showcase/src/app/client.tsx +1 -1
  174. package/samples/apps/showcase/src/app/shell.tsx +1 -1
  175. package/samples/apps/showcase/src/features/demos/web/index.ts +1 -1
  176. package/samples/apps/showcase/src/features/demos/web/pages/sidebar-panel.tsx +1 -1
  177. package/samples/apps/showcase/src/features/demos/web/pages/toast.tsx +1 -1
  178. package/samples/apps/showcase/src/features/items/web/index.ts +1 -1
  179. package/samples/apps/styleguide/package.json +1 -3
  180. package/samples/apps/styleguide/src/app/client.tsx +1 -1
  181. package/samples/apps/styleguide/src/app/shell.tsx +2 -2
  182. package/samples/apps/styleguide/src/features/ai-settings/web.ts +1 -1
  183. package/samples/apps/styleguide/src/features/content/web.tsx +2 -2
  184. package/samples/apps/styleguide/src/features/demo/web.ts +1 -1
  185. package/samples/apps/styleguide/src/features/examples/web.ts +1 -1
  186. package/samples/apps/styleguide/src/features/gallery/web/Gallery.tsx +1 -1
  187. package/samples/apps/styleguide/src/features/gallery/web/index.ts +1 -1
  188. package/samples/apps/styleguide/src/features/widgets/demo-locale.ts +1 -1
  189. package/samples/apps/styleguide/src/features/widgets/lib/format.ts +1 -1
  190. package/samples/apps/styleguide/src/features/widgets/web/DashboardFilterEcho.tsx +1 -1
  191. package/samples/apps/styleguide/src/features/widgets/web/FormExamples.tsx +1 -1
  192. package/samples/apps/styleguide/src/features/widgets/web/Widgets.tsx +1 -1
  193. package/samples/apps/styleguide/src/features/widgets/web/index.ts +1 -1
  194. package/samples/apps/styleguide/tsconfig.json +0 -12
  195. package/samples/apps/ui-walkthrough/package.json +1 -3
  196. package/samples/apps/ui-walkthrough/src/app/client.tsx +1 -1
  197. package/samples/apps/ui-walkthrough/src/app/help-action.tsx +37 -0
  198. package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +2 -0
  199. package/samples/apps/ui-walkthrough/src/app/shell.tsx +7 -1
  200. package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +20 -0
  201. package/samples/apps/ui-walkthrough/src/features/billing/web/index.ts +1 -1
  202. package/samples/apps/ui-walkthrough/src/features/rental/feature.ts +65 -1
  203. package/samples/apps/ui-walkthrough/src/features/rental/i18n.ts +70 -0
  204. package/samples/apps/ui-walkthrough/src/features/rental/invoice-receive.ts +20 -0
  205. package/samples/apps/ui-walkthrough/src/features/rental/lease-support.ts +15 -0
  206. package/samples/apps/ui-walkthrough/src/features/rental/qualified-names.ts +2 -0
  207. package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +79 -0
  208. package/samples/apps/ui-walkthrough/src/features/rental/web/index.ts +3 -1
  209. package/samples/apps/ui-walkthrough/src/features/rental/web/upload-standard-layout.tsx +61 -0
  210. package/samples/apps/ui-walkthrough/src/features/tasks/i18n.ts +8 -0
  211. package/samples/apps/ui-walkthrough/src/features/tasks/web/index.ts +1 -1
  212. package/samples/apps/ui-walkthrough/src/features/vehicles/web/index.ts +1 -1
  213. package/samples/apps/ui-walkthrough/src/run-config.ts +32 -3
  214. package/samples/apps/use-all-bundled/bin/main.ts +3 -2
  215. package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +12 -0
  216. package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +1 -1
  217. package/samples/apps/use-all-bundled/feature-manifest.json +3 -2
  218. package/samples/apps/use-all-bundled/package.json +1 -3
  219. package/samples/apps/use-all-bundled/src/app/client.tsx +1 -1
  220. package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +5 -4
  221. package/samples/apps/use-all-bundled/src/app/shell.tsx +1 -1
  222. package/samples/apps/use-all-bundled/src/run-config.ts +10 -1
  223. package/samples/apps/workspaces/package.json +1 -3
  224. package/samples/apps/workspaces/src/app/client.tsx +1 -1
  225. package/samples/apps/workspaces/src/app/shell.tsx +1 -1
  226. package/samples/apps/workspaces/src/features/demo/web/index.ts +1 -1
  227. package/samples/apps/workspaces/src/features/demo-driver/web/index.ts +1 -1
  228. package/samples/recipes/apex-landing/package.json +1 -1
  229. package/samples/recipes/apex-landing/src/feature.ts +1 -1
  230. package/samples/recipes/apex-surface-auth/README.md +1 -1
  231. package/samples/recipes/apex-surface-auth/src/feature.ts +2 -2
  232. package/samples/recipes/compose-stacks/README.md +7 -4
  233. package/samples/recipes/delivery-notifications/README.md +1 -1
  234. package/samples/recipes/embedded/README.md +8 -0
  235. package/samples/recipes/embedded/src/feature.ts +8 -0
  236. package/samples/recipes/embedded/src/handlers/invoice-receive.write.ts +38 -0
  237. package/samples/recipes/embedded/src/screens/invoice-receive.screen.ts +59 -0
  238. package/samples/recipes/embedded-entity-form/package.json +0 -1
  239. package/samples/recipes/embedded-entity-form/src/web/accept-suggestion-drawer.tsx +1 -1
  240. package/samples/recipes/notes-history-basic/README.md +1 -1
  241. package/samples/recipes/record-detail-layout/package.json +0 -1
  242. package/samples/recipes/tags-basic/README.md +1 -1
  243. package/samples/recipes/user-profile/README.md +1 -1
  244. package/samples/recipes/wizard-form/package.json +0 -1
  245. package/samples/recipes/wizard-form/src/web/index.ts +2 -2
  246. package/samples/recipes/wizard-form/src/web/listing-review-section.tsx +2 -2
  247. package/samples/recipes/writeform-section/package.json +0 -1
@@ -12,7 +12,7 @@ import {
12
12
  useTranslation,
13
13
  VariableChips,
14
14
  } from "@cosmicdrift/kumiko-renderer";
15
- import { cn } from "@cosmicdrift/kumiko-renderer-web";
15
+ import { cn } from "@cosmicdrift/kumiko-renderer/web";
16
16
  import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
17
17
  import type { Editor, JSONContent } from "@tiptap/core";
18
18
  import { EditorContent, useEditor, useEditorState } from "@tiptap/react";
@@ -25,6 +25,7 @@ import {
25
25
  Bold as BoldIcon,
26
26
  Braces,
27
27
  ChevronDown,
28
+ GalleryThumbnails,
28
29
  Image as ImageIcon,
29
30
  Italic as ItalicIcon,
30
31
  Link as LinkIcon,
@@ -72,7 +73,15 @@ function previewsKey(previews: Readonly<Record<string, DocumentResourcePreview>>
72
73
  .join("\n");
73
74
  }
74
75
 
75
- type PanelKind = "link" | "placeholder" | "image" | "button" | "repeat" | "align" | "steps";
76
+ type PanelKind =
77
+ | "link"
78
+ | "placeholder"
79
+ | "image"
80
+ | "button"
81
+ | "repeat"
82
+ | "align"
83
+ | "steps"
84
+ | "images";
76
85
 
77
86
  // Blocks that stay in the canvas toolbar; the rest moves into the overflow menu.
78
87
  const CANVAS_INLINE_BLOCKS: readonly DocumentToolbarBlock[] = ["image", "table"];
@@ -83,6 +92,7 @@ const BLOCK_PANEL: Partial<Record<DocumentToolbarBlock, PanelKind>> = {
83
92
  repeat: "repeat",
84
93
  align: "align",
85
94
  steps: "steps",
95
+ images: "images",
86
96
  };
87
97
 
88
98
  const ALIGNMENT_ICONS: Record<DocumentTextAlignment, ReactNode> = {
@@ -392,7 +402,11 @@ function InsertPanel({
392
402
  };
393
403
 
394
404
  const needsVariables =
395
- kind === "button" || kind === "repeat" || kind === "placeholder" || kind === "steps";
405
+ kind === "button" ||
406
+ kind === "repeat" ||
407
+ kind === "placeholder" ||
408
+ kind === "steps" ||
409
+ kind === "images";
396
410
  const noVariables = needsVariables && selectable.length === 0;
397
411
  const idPrefix = `${editorId}-panel`;
398
412
 
@@ -498,6 +512,16 @@ function InsertPanel({
498
512
  onChange={setChosenName}
499
513
  />
500
514
  )}
515
+ {kind === "images" && !noVariables && (
516
+ <NameSelect
517
+ id={`${idPrefix}-images-variable`}
518
+ label={t("template-resolver.documentEditor.imagesVariable")}
519
+ names={selectable}
520
+ labels={variableLabels}
521
+ value={selectedName}
522
+ onChange={setChosenName}
523
+ />
524
+ )}
501
525
  {kind === "steps" && !noVariables && (
502
526
  <>
503
527
  <NameSelect
@@ -551,6 +575,10 @@ function InsertPanel({
551
575
  {...(kind === "repeat" &&
552
576
  !noVariables && { onInsert: () => insertAndClose(repeatTableContent(selectedName)) })}
553
577
  {...(kind === "steps" && !noVariables && { onInsert: submitSteps })}
578
+ {...(kind === "images" &&
579
+ !noVariables && {
580
+ onInsert: () => insertAndClose({ type: "images", attrs: { variable: selectedName } }),
581
+ })}
554
582
  />
555
583
  </div>
556
584
  </div>
@@ -563,7 +591,8 @@ export default function DocumentTiptapEditor({
563
591
  onChange,
564
592
  variables,
565
593
  readOnly,
566
- blocks = MAIL_DOCUMENT_BLOCKS,
594
+ blocks: configuredBlocks = MAIL_DOCUMENT_BLOCKS,
595
+ imageVariables = NO_NAMES,
567
596
  variableLabels = NO_LABELS,
568
597
  systemVariables = NO_NAMES,
569
598
  resourcePreviews = NO_PREVIEWS,
@@ -581,6 +610,11 @@ export default function DocumentTiptapEditor({
581
610
  const canvas = chrome === "canvas";
582
611
  const compact = toolbar === "compact" && !canvas;
583
612
  const hosted = toolbarHost !== undefined;
613
+ // A photo block needs an images variable to bind to; without one the button would open an empty panel.
614
+ const blocks =
615
+ imageVariables.length === 0
616
+ ? configuredBlocks.filter((block) => block !== "images")
617
+ : configuredBlocks;
584
618
 
585
619
  const placeholderLabel = t("template-resolver.documentEditor.placeholder");
586
620
  const imageLabel = t("template-resolver.documentEditor.image");
@@ -588,6 +622,7 @@ export default function DocumentTiptapEditor({
588
622
  const pageBreakLabel = t("template-resolver.documentEditor.pageBreak");
589
623
  const buttonLabel = t("template-resolver.documentEditor.button");
590
624
  const stepsLabel = t("template-resolver.documentEditor.steps");
625
+ const imagesLabel = t("template-resolver.documentEditor.images");
591
626
  const stableLabels = useStableByKey(variableLabels, JSON.stringify(variableLabels));
592
627
  const stableSystem = useStableByKey(systemVariables, systemVariables.join("\n"));
593
628
  const stablePreviews = useStableByKey(resourcePreviews, previewsKey(resourcePreviews));
@@ -599,6 +634,7 @@ export default function DocumentTiptapEditor({
599
634
  pageBreak: pageBreakLabel,
600
635
  button: buttonLabel,
601
636
  steps: stepsLabel,
637
+ images: imagesLabel,
602
638
  imageBlock: imageBlockLabel,
603
639
  variableLabels: stableLabels,
604
640
  systemVariables: stableSystem,
@@ -612,6 +648,7 @@ export default function DocumentTiptapEditor({
612
648
  pageBreakLabel,
613
649
  buttonLabel,
614
650
  stepsLabel,
651
+ imagesLabel,
615
652
  stableLabels,
616
653
  stableSystem,
617
654
  stablePreviews,
@@ -731,6 +768,7 @@ export default function DocumentTiptapEditor({
731
768
  pageBreak: { label: pageBreakLabel, icon: <Scissors size={16} /> },
732
769
  align: { label: t("template-resolver.documentEditor.align"), icon: <AlignLeft size={16} /> },
733
770
  steps: { label: stepsLabel, icon: <ListChecks size={16} /> },
771
+ images: { label: imagesLabel, icon: <GalleryThumbnails size={16} /> },
734
772
  };
735
773
 
736
774
  const repeatTable = activeState?.repeatTable ?? null;
@@ -1058,7 +1096,7 @@ export default function DocumentTiptapEditor({
1058
1096
  editor={editor}
1059
1097
  editorId={id}
1060
1098
  kind={openPanel}
1061
- variables={variables}
1099
+ variables={openPanel === "images" ? imageVariables : variables}
1062
1100
  variableLabels={stableLabels}
1063
1101
  onClose={() => setOpenPanel(null)}
1064
1102
  />
@@ -1,16 +1,7 @@
1
1
  // @runtime client
2
2
  import type { ContentEditorProps } from "@cosmicdrift/kumiko-renderer";
3
3
  import type { ReactNode } from "react";
4
-
5
- export type DocumentToolbarBlock =
6
- | "image"
7
- | "table"
8
- | "button"
9
- | "divider"
10
- | "repeat"
11
- | "pageBreak"
12
- | "align"
13
- | "steps";
4
+ import type { DocumentToolbarBlock } from "../document-blocks.ts";
14
5
 
15
6
  /** Imperative access for an outside panel (placeholder list, resource list). */
16
7
  export type DocumentEditorHandle = {
@@ -31,6 +22,8 @@ export type DocumentEditorChrome = "default" | "canvas";
31
22
 
32
23
  export type DocumentEditorProps = ContentEditorProps & {
33
24
  readonly blocks?: readonly DocumentToolbarBlock[];
25
+ /** Names of the template's images variables; the photo block offers exactly these and is hidden without any. */
26
+ readonly imageVariables?: readonly string[];
34
27
  /** Display label per variable name, as inserted (list item fields use the
35
28
  * dotted form, e.g. "lines.description"). A chip shows label and name. */
36
29
  readonly variableLabels?: Readonly<Record<string, string>>;
@@ -50,26 +43,9 @@ export type DocumentEditorProps = ContentEditorProps & {
50
43
  readonly onEditorReady?: (handle: DocumentEditorHandle | null) => void;
51
44
  };
52
45
 
53
- export const MAIL_DOCUMENT_BLOCKS = [
54
- "image",
55
- "table",
56
- "button",
57
- "divider",
58
- "repeat",
59
- "steps",
60
- ] as const satisfies readonly DocumentToolbarBlock[];
61
-
62
- export const PDF_DOCUMENT_BLOCKS = [
63
- "align",
64
- "image",
65
- "table",
66
- "divider",
67
- "repeat",
68
- "steps",
69
- "pageBreak",
70
- ] as const satisfies readonly DocumentToolbarBlock[];
71
-
72
- /** Block set for a template-resource kind; every kind except "document-pdf" gets the mail set. */
73
- export function documentBlocksForKind(kind: string | undefined): readonly DocumentToolbarBlock[] {
74
- return kind === "document-pdf" ? PDF_DOCUMENT_BLOCKS : MAIL_DOCUMENT_BLOCKS;
75
- }
46
+ export {
47
+ type DocumentToolbarBlock,
48
+ documentBlocksForKind,
49
+ MAIL_DOCUMENT_BLOCKS,
50
+ PDF_DOCUMENT_BLOCKS,
51
+ } from "../document-blocks.ts";
@@ -43,6 +43,8 @@ export const defaultTranslations: TranslationsByLocale = {
43
43
  "template-resolver.documentEditor.removeLink": "Remove link",
44
44
  "template-resolver.documentEditor.repeat": "Repeat",
45
45
  "template-resolver.documentEditor.repeatList": "List to repeat",
46
+ "template-resolver.documentEditor.images": "Photos",
47
+ "template-resolver.documentEditor.imagesVariable": "Photos from",
46
48
  "template-resolver.documentEditor.steps": "Steps",
47
49
  "template-resolver.documentEditor.stepsVariable": "Current step from",
48
50
  "template-resolver.documentEditor.stepsList": "Steps, separated by commas (value=label)",
@@ -58,6 +60,8 @@ export const defaultTranslations: TranslationsByLocale = {
58
60
  "template-resolver.editor.saving": "Saving…",
59
61
  "template-resolver.editor.created": "Created.",
60
62
  "template-resolver.editor.saved": "Saved.",
63
+ "templateResolver.errors.document.imagesBlockPdfOnly":
64
+ "Photo blocks are only allowed in PDF documents.",
61
65
  "templateResolver.errors.document.buttonHrefNotPlaceholder":
62
66
  "The button target “{detail}” must be a placeholder.",
63
67
  "templateResolver.errors.document.disallowedLinkHref":
@@ -80,6 +84,30 @@ export const defaultTranslations: TranslationsByLocale = {
80
84
  "templateResolver.checks.sizeUnderCap": "The mail is within the 10 MiB size limit",
81
85
  "templateResolver.checks.requiredPlaceholders": "All required placeholders are used",
82
86
  "templateResolver.errors.preview.renderFailed": "The preview could not be rendered.",
87
+ "templateResolver.errors.patch.unknownBlock":
88
+ "The block {blockId} does not exist in the template.",
89
+ "templateResolver.errors.patch.blockRemoved":
90
+ "The block {blockId} was already removed by an earlier step.",
91
+ "templateResolver.errors.patch.textNotFound": "The text {find} was not found in the block.",
92
+ "templateResolver.errors.patch.textAmbiguous":
93
+ "The text {find} occurs {count} times in the block; use a longer text.",
94
+ "templateResolver.errors.patch.blockNotAllowed":
95
+ "The block type {type} is not available in {kind} templates.",
96
+ "templateResolver.errors.patch.blockTypeMismatch":
97
+ "This step needs a {expected} block, but the block is a {actual}.",
98
+ "templateResolver.errors.patch.invalidResourceKey": "The image key {resource} is not valid.",
99
+ "templateResolver.errors.patch.invalidButtonHref":
100
+ "A button target must be a placeholder in double curly braces.",
101
+ "templateResolver.errors.patch.invalidVariableName": "The variable name {name} is not valid.",
102
+ "templateResolver.errors.patch.invalidVariableDefinition":
103
+ "The definition of the variable {name} is not valid.",
104
+ "templateResolver.errors.patch.invalidDocument":
105
+ "The change would produce an invalid document.",
106
+ "templateResolver.errors.patch.invalidMetaKey": "The meta key {key} is not allowed.",
107
+ "templateResolver.errors.patch.variablesDeclaredByFeature":
108
+ "The variables of {slug} are fixed by the application and cannot be changed.",
109
+ "templateResolver.errors.patch.requiredPlaceholderRemoved":
110
+ "The change removes required placeholders: {names}",
83
111
  "templateResolver.errors.testMail.noChannel":
84
112
  "No email channel is set up, so no test mail can be sent.",
85
113
  "templateResolver.errors.testMail.noAddress":
@@ -98,6 +126,8 @@ export const defaultTranslations: TranslationsByLocale = {
98
126
  "templateResolver.errors.noDraft": "There is no draft to discard.",
99
127
  "templateResolver.errors.systemOnlyTemplate":
100
128
  "Only the platform maintains this template; it cannot be overridden per tenant.",
129
+ "templateResolver.errors.templateNotTenantEditable":
130
+ "Only the platform may edit this template.",
101
131
  "templateResolver.errors.template.invalidMeta": "The template settings are invalid.",
102
132
  "templateResolver.errors.template.meta.subject.required": "The subject is missing.",
103
133
  "templateResolver.errors.template.meta.subject.invalid":
@@ -4,17 +4,17 @@
4
4
  // (subject, preheader). The stored value stays plain text; placeholders show
5
5
  // as chips while editing. Lives in the same lazy chunk as the document editor.
6
6
 
7
- import { cn } from "@cosmicdrift/kumiko-renderer-web";
7
+ import { cn } from "@cosmicdrift/kumiko-renderer/web";
8
8
  import { Extension, Node } from "@tiptap/core";
9
9
  import { Placeholder, UndoRedo } from "@tiptap/extensions";
10
10
  import { EditorContent, useEditor } from "@tiptap/react";
11
11
  import StarterKit from "@tiptap/starter-kit";
12
12
  import { type ReactNode, useMemo, useState } from "react";
13
13
  import { DocumentVariable } from "../document-schema.ts";
14
+ import { contentToLine, lineToContent, singleLine } from "../placeholder-text.ts";
14
15
  import { createVariableView } from "./document-editor-extensions.ts";
15
16
  import type { DocumentEditorHandle } from "./document-toolbar-blocks.ts";
16
17
  import { createEditorHandle } from "./editor-handle.ts";
17
- import { contentToLine, lineToContent, singleLine } from "./placeholder-text.ts";
18
18
  import { useStableByKey } from "./use-stable-by-key.ts";
19
19
 
20
20
  export type PlaceholderLineEditorProps = {
@@ -1,6 +1,6 @@
1
1
  // @runtime client
2
2
  import { mergeTranslations, type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
3
- import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer-web";
3
+ import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
4
4
  import {
5
5
  MEMBER_ROLES_CELL_COMPONENT,
6
6
  MEMBER_STATUS_CELL_COMPONENT,
@@ -5,7 +5,7 @@
5
5
  // projectionList renderer — only this one cell stays TSX.
6
6
 
7
7
  import { type ColumnRendererProps, useTranslation } from "@cosmicdrift/kumiko-renderer";
8
- import { StatusBadge, type StatusTone } from "@cosmicdrift/kumiko-renderer-web";
8
+ import { StatusBadge, type StatusTone } from "@cosmicdrift/kumiko-renderer/web";
9
9
  import type { ReactNode } from "react";
10
10
  import { translateOrRaw } from "../../shared/web/translate-or-raw.ts";
11
11
 
@@ -8,7 +8,7 @@ import {
8
8
  type TranslationsByLocale,
9
9
  translationsByLocaleFromKeys,
10
10
  } from "@cosmicdrift/kumiko-renderer";
11
- import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer-web";
11
+ import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
12
12
  import { TIER_ENGINE_FEATURE } from "../constants.ts";
13
13
  import { TIER_ENGINE_I18N } from "../i18n.ts";
14
14
 
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.376.0",
4
+ "type": "improvement",
5
+ "title": "DELETION_TOKEN_SECRET is part of the env schema",
6
+ "detail": "The feature declares DELETION_TOKEN_SECRET through its env schema, so the dry run and the pulumi inventory list it. Unset, it is derived from JWT_SECRET as before."
7
+ },
2
8
  {
3
9
  "version": "0.372.0",
4
10
  "type": "fix",
@@ -0,0 +1,15 @@
1
+ import * as z from "zod";
2
+
3
+ const MIN_DELETION_TOKEN_SECRET_LENGTH = 32;
4
+
5
+ /** Optional dedicated HMAC key of the anonymous deletion-confirmation links. */
6
+ export const deletionTokenSecretEnvSchema = z.object({
7
+ DELETION_TOKEN_SECRET: z
8
+ .string()
9
+ .min(MIN_DELETION_TOKEN_SECRET_LENGTH)
10
+ .optional()
11
+ .describe(
12
+ "Dedicated HMAC secret for the anonymous deletion-confirmation links. Unset: derived from JWT_SECRET.",
13
+ )
14
+ .meta({ kumiko: { pulumi: { generator: "openssl rand -hex 24", secret: true } } }),
15
+ });
@@ -25,6 +25,7 @@ import {
25
25
  USER_ME_QUERY,
26
26
  UserDataRightsHandlers,
27
27
  } from "./constants.ts";
28
+ import { deletionTokenSecretEnvSchema } from "./env.ts";
28
29
  import { cancelDeletionWrite } from "./handlers/cancel-deletion.write.ts";
29
30
  import { createConfirmDeletionByTokenHandler } from "./handlers/confirm-deletion-by-token.write.ts";
30
31
  import { downloadAttemptListQuery } from "./handlers/download-attempt-list.query.ts";
@@ -198,6 +199,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
198
199
  recommended: false,
199
200
  });
200
201
  r.requires({ features: ["user", "data-retention", "compliance-profiles", "sessions"] });
202
+ r.envSchema(deletionTokenSecretEnvSchema);
201
203
  r.usesApi("compliance.forTenant");
202
204
  r.usesApi("retention.policyFor");
203
205
  // S2.U6 — restrict-account ruft sessions.revokeAllForUser cross-feature.
@@ -615,7 +617,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
615
617
  // SYSTEM_USER_ID ist die framework-weite Konvention. Der job-
616
618
  // Discriminator wird via handlerName="user-data-rights:run-export-
617
619
  // jobs" im Secret-Read-Audit erfasst.
618
- const exportUserId = ctx._userId ?? SYSTEM_USER_ID;
620
+ const exportUserId = SYSTEM_USER_ID;
619
621
  const exportDb =
620
622
  ctx.db.unsafeRaw() as import("@cosmicdrift/kumiko-framework/db").DbConnection; // @cast-boundary db-operator — jobs never run inside a DbTx
621
623
  const exportRegistry = ctx.registry;
@@ -708,7 +710,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
708
710
  throw new Error("run-forget-cleanup: ctx.registry required (JobContext incomplete)");
709
711
  }
710
712
  const T = (await import("@cosmicdrift/kumiko-framework/time")).getTemporal();
711
- const forgetUserId = ctx._userId ?? SYSTEM_USER_ID;
713
+ const forgetUserId = SYSTEM_USER_ID;
712
714
  const forgetDb =
713
715
  ctx.db.unsafeRaw() as import("@cosmicdrift/kumiko-framework/db").DbConnection; // @cast-boundary db-operator — jobs never run inside a DbTx
714
716
  const forgetRegistry = ctx.registry;
@@ -1,4 +1,5 @@
1
1
  export { TENANT_MODEL_CONFIG_KEY } from "./constants.ts";
2
+ export { deletionTokenSecretEnvSchema } from "./env.ts";
2
3
  export { createUserDataRightsFeature, type UserDataRightsOptions } from "./feature.ts";
3
4
  export type { SendDeletionVerificationEmailFn } from "./handlers/request-deletion-by-email.write.ts";
4
5
  export {
@@ -42,7 +42,7 @@ export function makeTenantMailTransportResolver(
42
42
  ctx.db,
43
43
  );
44
44
  return createTransportForTenant(
45
- { config, registry: ctx.registry, secrets: ctx.secrets, _userId: ctx.userId },
45
+ { config, registry: ctx.registry, secrets: ctx.secrets, auditUserId: ctx.userId },
46
46
  tenantId,
47
47
  ctx.handlerName,
48
48
  );
@@ -41,7 +41,7 @@ export function makeTenantStorageProviderResolver(
41
41
  ctx.db,
42
42
  );
43
43
  return createFileProviderForTenant(
44
- { config, registry: ctx.registry, secrets: ctx.secrets, _userId: ctx.userId },
44
+ { config, registry: ctx.registry, secrets: ctx.secrets, auditUserId: ctx.userId },
45
45
  tenantId,
46
46
  ctx.handlerName,
47
47
  );
@@ -12,7 +12,7 @@ import {
12
12
  mailT,
13
13
  resolveMailLocale,
14
14
  } from "@cosmicdrift/kumiko-framework/i18n";
15
- import { escapeHtml } from "@cosmicdrift/kumiko-headless";
15
+ import { escapeHtml } from "@cosmicdrift/kumiko-renderer/headless";
16
16
  import { mailParagraph } from "../shared/index.ts";
17
17
  import { USER_DATA_RIGHTS_FEATURE } from "./constants.ts";
18
18
 
@@ -16,7 +16,7 @@
16
16
  // money-horse) must carry the option over at feature setup.
17
17
 
18
18
  import { mergeTranslations, type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
19
- import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer-web";
19
+ import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
20
20
  import { EXPORT_SECTION_EXTENSION_NAME, USER_DATA_RIGHTS_FEATURE } from "../constants.ts";
21
21
  import { defaultTranslations } from "./i18n.ts";
22
22
  import { ExportSection } from "./privacy-center-screen.tsx";
@@ -1,4 +1,4 @@
1
- import { EMPTY_VALUE_PLACEHOLDER } from "@cosmicdrift/kumiko-headless";
1
+ import { EMPTY_VALUE_PLACEHOLDER } from "@cosmicdrift/kumiko-renderer/headless";
2
2
  // @runtime client
3
3
  // Export section (Art. 20) — the one part of user-data-rights' privacy-center
4
4
  // screen that stays custom (fw#2312). Registered as an EditExtensionSection
@@ -17,7 +17,7 @@ import {
17
17
  useQuery,
18
18
  useTranslation,
19
19
  } from "@cosmicdrift/kumiko-renderer";
20
- import { postWithDownload } from "@cosmicdrift/kumiko-renderer-web";
20
+ import { postWithDownload } from "@cosmicdrift/kumiko-renderer/web";
21
21
  import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
22
22
  import { type ReactNode, useEffect, useState } from "react";
23
23
  import {
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.377.0",
4
+ "type": "fix",
5
+ "title": "migrateLegacyWaitlist no longer replays legacy events on rebuild",
6
+ "detail": "The legacy event stream of each migrated row is archived, so a projection rebuild does not resurrect the old id next to the imported entry. The report gains archivedStreams."
7
+ },
2
8
  {
3
9
  "version": "0.370.0",
4
10
  "type": "breaking",
@@ -5,6 +5,7 @@ import {
5
5
  PII_ERASED_SENTINEL,
6
6
  } from "@cosmicdrift/kumiko-framework/crypto";
7
7
  import {
8
+ countWhere,
8
9
  createTenantDb,
9
10
  selectMany,
10
11
  table,
@@ -14,10 +15,16 @@ import {
14
15
  uuid,
15
16
  } from "@cosmicdrift/kumiko-framework/db";
16
17
  import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
18
+ import {
19
+ archiveStream,
20
+ createArchivedStreamsTable,
21
+ eventsTable,
22
+ isStreamArchived,
23
+ } from "@cosmicdrift/kumiko-framework/event-store";
17
24
  import type { DbConnection } from "@cosmicdrift/kumiko-types/db-connection";
18
25
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
19
26
  import { WAITLIST_STATUS, type WaitlistStatus } from "./constants.ts";
20
- import { importWaitlistEntry, type WaitlistImportEntry } from "./import.ts";
27
+ import { importWaitlistEntry, type WaitlistImportEntry, waitlistImportId } from "./import.ts";
21
28
 
22
29
  export const LEGACY_WAITLIST_SOURCES = ["offlot", "publicstatus"] as const;
23
30
  export type LegacyWaitlistSource = (typeof LEGACY_WAITLIST_SOURCES)[number];
@@ -46,8 +53,13 @@ export type LegacyWaitlistMigrateReport = {
46
53
  readonly created: number;
47
54
  readonly skipped: number;
48
55
  readonly unreadable: number;
56
+ /** Event streams of the legacy rows (same aggregate type) taken out of projection replay. */
57
+ readonly archivedStreams: number;
49
58
  };
50
59
 
60
+ const LEGACY_AGGREGATE_TYPE = "waitlistEntry";
61
+ const LEGACY_STREAM_ARCHIVE_REASON = "migrated to a new waitlist entry id by waitlist-migrate";
62
+
51
63
  type LegacyRow = Readonly<Record<string, unknown>>;
52
64
 
53
65
  function toInstant(value: unknown): Temporal.Instant | undefined {
@@ -189,6 +201,34 @@ async function readLegacyRows(
189
201
  });
190
202
  }
191
203
 
204
+ // A legacy offlot row is the projection of an event stream of the same aggregate type under the
205
+ // old row id, written in the system tenant like every waitlist entry. The imported entry gets a
206
+ // new id, so a rebuild would replay the old stream next to it and bring every migrated entry back
207
+ // twice; archived streams are excluded from replay. The offlot default source table is the entity
208
+ // table itself, so its row ids are live entries by design and no id check can tell a wrong table.
209
+ async function archiveLegacyStream(
210
+ db: DbConnection,
211
+ legacyId: string,
212
+ importedId: string,
213
+ ): Promise<number> {
214
+ if (legacyId === importedId) return 0;
215
+ if (await isStreamArchived(db, SYSTEM_TENANT_ID, legacyId)) return 0;
216
+ const legacyEvents = await countWhere(db, eventsTable, {
217
+ tenantId: SYSTEM_TENANT_ID,
218
+ aggregateId: legacyId,
219
+ aggregateType: LEGACY_AGGREGATE_TYPE,
220
+ });
221
+ if (legacyEvents === 0) return 0;
222
+ await archiveStream(db, {
223
+ tenantId: SYSTEM_TENANT_ID,
224
+ aggregateId: legacyId,
225
+ aggregateType: LEGACY_AGGREGATE_TYPE,
226
+ archivedBy: "waitlist-migrate",
227
+ reason: LEGACY_STREAM_ARCHIVE_REASON,
228
+ });
229
+ return 1;
230
+ }
231
+
192
232
  // Idempotent: the new entry id derives from the source row id, so a re-run finds
193
233
  // what an earlier run wrote and skips it. Writes go through the waitlist entity
194
234
  // executor (events, projection, subject encryption), never into tables directly.
@@ -200,6 +240,8 @@ export async function migrateLegacyWaitlist(
200
240
  let created = 0;
201
241
  let skipped = 0;
202
242
  let unreadable = 0;
243
+ let archivedStreams = 0;
244
+ if (!options.dryRun && options.from === "offlot") await createArchivedStreamsTable(db);
203
245
  for (const row of rows) {
204
246
  const entry =
205
247
  options.from === "offlot"
@@ -215,6 +257,13 @@ export async function migrateLegacyWaitlist(
215
257
  if (outcome === "created") created += 1;
216
258
  else skipped += 1;
217
259
  });
260
+ if (!options.dryRun && options.from === "offlot") {
261
+ archivedStreams += await archiveLegacyStream(
262
+ db,
263
+ String(row["id"]),
264
+ waitlistImportId(entry.sourceKey),
265
+ );
266
+ }
218
267
  }
219
- return { read: rows.length, created, skipped, unreadable };
268
+ return { read: rows.length, created, skipped, unreadable, archivedStreams };
220
269
  }
@@ -9,11 +9,8 @@
9
9
  "dependencies": {
10
10
  "@cosmicdrift/kumiko-bundled-features": "workspace:*",
11
11
  "@cosmicdrift/kumiko-dev-server": "workspace:*",
12
- "@cosmicdrift/kumiko-dispatcher-live": "workspace:*",
13
12
  "@cosmicdrift/kumiko-framework": "workspace:*",
14
- "@cosmicdrift/kumiko-headless": "workspace:*",
15
13
  "@cosmicdrift/kumiko-renderer": "workspace:*",
16
- "@cosmicdrift/kumiko-renderer-web": "workspace:*",
17
14
  "lucide-react": "^1.14.0",
18
15
  "react": "^19.2.6",
19
16
  "react-dom": "^19.2.6",
@@ -5,7 +5,7 @@ import { jobsClient } from "@cosmicdrift/kumiko-bundled-features/jobs/web";
5
5
  import { tenantClient } from "@cosmicdrift/kumiko-bundled-features/tenant/web";
6
6
  import { tierEngineClient } from "@cosmicdrift/kumiko-bundled-features/tier-engine/web";
7
7
  import { localeDeClient } from "@cosmicdrift/kumiko-locale-de/web";
8
- import { createKumikoApp } from "@cosmicdrift/kumiko-renderer-web";
8
+ import { createKumikoApp } from "@cosmicdrift/kumiko-renderer/web";
9
9
  import { HomeScreen } from "./home-screen";
10
10
  import { AppShell } from "./shell";
11
11
 
@@ -2,7 +2,7 @@ import {
2
2
  DefaultTopbarActions,
3
3
  useShellUser,
4
4
  } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/web";
5
- import { type AppSchema, WorkspaceShell } from "@cosmicdrift/kumiko-renderer-web";
5
+ import { type AppSchema, WorkspaceShell } from "@cosmicdrift/kumiko-renderer/web";
6
6
  import { MoonStar, Sun } from "lucide-react";
7
7
  import type { ReactNode } from "react";
8
8
 
@@ -11,10 +11,8 @@
11
11
  "dependencies": {
12
12
  "@cosmicdrift/kumiko-bundled-features": "workspace:*",
13
13
  "@cosmicdrift/kumiko-dev-server": "workspace:*",
14
- "@cosmicdrift/kumiko-dispatcher-live": "workspace:*",
14
+ "@cosmicdrift/kumiko-renderer": "workspace:*",
15
15
  "@cosmicdrift/kumiko-framework": "workspace:*",
16
- "@cosmicdrift/kumiko-headless": "workspace:*",
17
- "@cosmicdrift/kumiko-renderer-web": "workspace:*",
18
16
  "react": "^19.2.6",
19
17
  "react-dom": "^19.2.6",
20
18
  "@cosmicdrift/kumiko-locale-de": "workspace:*"
@@ -1,6 +1,6 @@
1
1
  import { configClient } from "@cosmicdrift/kumiko-bundled-features/config/web";
2
2
  import { localeDeClient } from "@cosmicdrift/kumiko-locale-de/web";
3
- import { createKumikoApp } from "@cosmicdrift/kumiko-renderer-web";
3
+ import { createKumikoApp } from "@cosmicdrift/kumiko-renderer/web";
4
4
  import { configDemoClient } from "../features/demo/web";
5
5
  import { AppShell } from "./shell";
6
6
 
@@ -1,5 +1,5 @@
1
- import type { AppSchema } from "@cosmicdrift/kumiko-renderer-web";
2
- import { DefaultAppShell } from "@cosmicdrift/kumiko-renderer-web";
1
+ import type { AppSchema } from "@cosmicdrift/kumiko-renderer/web";
2
+ import { DefaultAppShell } from "@cosmicdrift/kumiko-renderer/web";
3
3
  import type { ReactNode } from "react";
4
4
 
5
5
  // Logo-Kachel + Wortmarke — wie SidebarBrand (sidebar-brand.tsx). Die
@@ -1,4 +1,4 @@
1
- import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer-web";
1
+ import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
2
2
  import { configDemoTranslations } from "../i18n";
3
3
 
4
4
  export const configDemoClient: ClientFeatureDefinition = {
@@ -14,18 +14,6 @@
14
14
  "@cosmicdrift/kumiko-dev-server/*": [
15
15
  "../../../packages/dev-server/src/*"
16
16
  ],
17
- "@cosmicdrift/kumiko-renderer-web": [
18
- "../../../packages/renderer-web/src/index.ts"
19
- ],
20
- "@cosmicdrift/kumiko-renderer-web/*": [
21
- "../../../packages/renderer-web/src/*"
22
- ],
23
- "@cosmicdrift/kumiko-dispatcher-live": [
24
- "../../../packages/dispatcher-live/src/index.ts"
25
- ],
26
- "@cosmicdrift/kumiko-headless": [
27
- "../../../packages/headless/src/index.ts"
28
- ],
29
17
  "@cosmicdrift/kumiko-renderer": [
30
18
  "../../../packages/renderer/src/index.ts"
31
19
  ],