You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Chatto stores and exchanges message bodies as plain text while the bundled client renders the deliberately limited Markdown subset documented in FDR-032. Mermaid fences would let people share architecture, sequence, state, and other diagrams while preserving that portable source contract.
The frontend currently routes fenced blocks through apps/frontend/src/lib/markdown.ts, lazy-loads syntax highlighting, and inserts renderer-owned output through MarkdownHtml.svelte. Mermaid is substantially heavier and emits user-influenced SVG, so it needs its own lazy, bounded, reviewed path rather than being treated as another highlighting language.
No protobuf or persisted-message schema change should be necessary. Older/third-party clients can continue to display the fenced source.
Proposed behavior
Use GitHub-compatible fenced syntax:
```mermaidflowchart LR Browser --> Chatto```
Only a fenced block whose normalized language is exactly mermaid becomes a diagram.
Preserve the original source through compose, send, edit, copy, reply quoting, realtime delivery, and history hydration.
While loading, keep a stable source/code fallback; on parse, render, security, or complexity failure, leave that individual fence readable as code instead of failing the whole message.
Do not execute diagram links, click handlers, scripts, raw HTML labels, or other interactive behavior.
Technical direction
Use Mermaid's programmatic render API with startOnLoad: false; do not scan the global document and do not call returned bindFunctions. Dynamically import Mermaid only when an actual Mermaid fence needs rendering and verify it stays out of representative initial-route chunks.
Security is part of the feature, not follow-up work:
Pin securityLevel: "strict", disable HTML labels and interactions, and retain site ownership of every security-sensitive option. Mermaid documents that strict mode encodes HTML and disables clicks, but generated SVG is still an untrusted-content boundary: sanitize it with an explicit SVG allowlist or isolate it in an equivalently reviewed boundary before DOM insertion.
Do not let message-authored directives or frontmatter relax security/resource configuration or inject CSS/HTML. Reject them initially unless a narrow safe allowlist is deliberately designed.
Preserve the existing single audited Markdown HTML sink/Trusted Types model; do not introduce feature-level {@html} usage.
Review CSP impact without adding broad unsafe-*, data:, remote-script, or remote-font allowances.
Keep Mermaid's dependencies bundled locally and update NOTICE.
Mermaid parsing/layout is attacker-controlled work. Set explicit limits below Mermaid's generous defaults for source size, edges/nodes, generated SVG size/dimensions, and diagrams per message. Also:
render only diagrams near/inside the viewport;
bound concurrent renders and cache completed SVGs by source plus theme in a bounded cache;
cancel or ignore stale results after unmount/source/theme changes;
ensure one expensive or broken diagram cannot block other messages;
avoid rerender loops in virtualized timelines.
Mermaid exposes maxTextSize and maxEdges, but those are not a complete DOM/output budget; add Chatto-side limits and adversarial tests too.
Accessibility and presentation
Support Mermaid accTitle and accDescr and verify the rendered graphic has an accessible name/description. See Mermaid's accessibility syntax.
Provide a readable source/error fallback when an accessible description is absent or rendering is unavailable.
Keep diagrams responsive inside the message width, with native overflow/zoom behavior where required; never widen the conversation layout.
Render legibly in every supported light/dark theme and update safely when the app theme changes.
Acceptance criteria
Valid flowchart, sequence, class/state, ER, and Git graph fences render from the standard mermaid code-fence syntax.
Non-Mermaid fences and malformed/unsupported/over-limit Mermaid fences retain readable code-block behavior.
Source round-trips unchanged through the rich composer, posting, editing, copy/reply actions, and receiver-side rendering.
Mermaid is lazy-loaded only for visible Mermaid content and absent from message-free initial chunks.
Site-owned strict security settings cannot be overridden by source; raw HTML, CSS injection, links, scripts, events, and bindFunctions are not active.
Generated SVG passes a reviewed sanitization/isolation boundary compatible with Trusted Types and CSP.
Source, edge/node, output, diagram-count, and concurrency limits prevent pathological messages from monopolizing the UI.
Rendering is stale-safe across virtual-list unmounts, message edits/deletes, and theme changes.
Diagrams are accessible, responsive, theme-aware, and do not widen or clip the message layout.
Parser/security/limit tests, mounted browser-component tests, realistic Storybook stories, and sender/receiver browser coverage exercise success and fallback paths.
FDR-032, the public Message Body Tokens documentation, user-facing formatting docs, dependency metadata, and NOTICE are updated.
Context
Chatto stores and exchanges message bodies as plain text while the bundled client renders the deliberately limited Markdown subset documented in FDR-032. Mermaid fences would let people share architecture, sequence, state, and other diagrams while preserving that portable source contract.
The frontend currently routes fenced blocks through
apps/frontend/src/lib/markdown.ts, lazy-loads syntax highlighting, and inserts renderer-owned output throughMarkdownHtml.svelte. Mermaid is substantially heavier and emits user-influenced SVG, so it needs its own lazy, bounded, reviewed path rather than being treated as another highlighting language.No protobuf or persisted-message schema change should be necessary. Older/third-party clients can continue to display the fenced source.
Proposed behavior
Use GitHub-compatible fenced syntax:
mermaidbecomes a diagram.Technical direction
Use Mermaid's programmatic render API with
startOnLoad: false; do not scan the global document and do not call returnedbindFunctions. Dynamically import Mermaid only when an actual Mermaid fence needs rendering and verify it stays out of representative initial-route chunks.Security is part of the feature, not follow-up work:
securityLevel: "strict", disable HTML labels and interactions, and retain site ownership of every security-sensitive option. Mermaid documents that strict mode encodes HTML and disables clicks, but generated SVG is still an untrusted-content boundary: sanitize it with an explicit SVG allowlist or isolate it in an equivalently reviewed boundary before DOM insertion.{@html}usage.unsafe-*,data:, remote-script, or remote-font allowances.NOTICE.See Mermaid's security-level contract and secure configuration keys.
Resource limits and rendering lifecycle
Mermaid parsing/layout is attacker-controlled work. Set explicit limits below Mermaid's generous defaults for source size, edges/nodes, generated SVG size/dimensions, and diagrams per message. Also:
Mermaid exposes
maxTextSizeandmaxEdges, but those are not a complete DOM/output budget; add Chatto-side limits and adversarial tests too.Accessibility and presentation
accTitleandaccDescrand verify the rendered graphic has an accessible name/description. See Mermaid's accessibility syntax.Acceptance criteria
mermaidcode-fence syntax.bindFunctionsare not active.NOTICEare updated.Out of scope