fix(mermaid): render diagrams on web via JS-interop (#851) #860
No reviewers
Labels
No labels
accepted
bug
declined
docs
duplicate
enhancement
good first issue
in-progress
needs-info
privacy
security
triage
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
LibreKAT/Ocideck!860
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/851-mermaid-web-render"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Sluit #851.
De bug
Een beslisboom-slide (vrije Markdown met een mermaid-codeblok) bleef op web een leeg vlak. De oorzaak zat een laag dieper dan de web-CSP: de renderer tekent de diagrammen in een verborgen WebView en leest de SVG terug met
runJavaScriptReturningResult— enwebview_flutter_webimplementeert die methode niet (erft deUnimplementedErroruitPlatformWebViewController). Elke render gaf daardoor stilnullen de preview viel terug op een leeg kader. Op desktop, met een echte WebView, werkte het wél.De fix
Op web draait mermaid nu rechtstreeks in de app-pagina in plaats van in een (niet-functionele) WebView:
mermaid.min.jswordt als eigen-origin<script src>geladen — dat mag onder de strikte app-CSP (script-src 'self'), en mermaid heeft geenevalnodig (de WebView-bootstrap draaide het al onder een CSP zonderunsafe-eval);mermaid.rendergaat viadart:js_interop(+package:web);mermaid_config.dart(kMermaidInitConfig), gebruikt door beide paden (JSON in de WebView-pagina,.jsify()op web), zodatsecurityLevel: 'strict'en de SVG-opschoning niet uiteen kunnen lopen.Verificatie
De echte web-render is onder
flutter testniet uit te voeren (kIsWebis er altijd false;dart:js_interopcompileert niet op de VM). Daarom:<script src>onder de exacte app-CSP, rendert een geldige SVG (13.896 tekens) zonder console-/CSP-fouten;make build-web, geserveerd): de app boot onder de productie-CSP, enmermaid.renderlevert een geldige SVG in de Flutter-web-DOM (bodyHasFlutter=true), geladen van de asset-URL die de renderer gebruikt;mermaid_web_render_test: bewaakt de structuur waar de bug in zat (gedeelde config is strikt, de web-script-URL klopt met wat pubspec bundelt, de service kiest achterkIsWebhet web-pad, beide paden gebruikenkMermaidInitConfig). De io-stub wordt rechtstreeks gedekt.Security-review
Beoordeeld door de security-architect (rolblik): akkoord. De vertrouwensgrens verschuift (geïsoleerde WebView → in-page), maar de app-CSP is op script-uitvoering zelfs strikter dan de oude WebView (die
script-src 'unsafe-inline'toestond); vier lagen dekken de transiënte DOM-insertie (securityLevel strict + DOMPurify, htmlLabels uit, de app-CSP, ensanitizeMermaidSvg+ render via flutter_svg zodat de SVG nooit als HTML de app-DOM in komt). Geen nieuw netwerkverkeer (zelfde-origin asset), fail-closed. Twee bevindingen weggewerkt: (1) de CSP-comment inweb/index.htmlschreef deframe-src blob:/data:-ontheffing nog aan de mermaid-WebView toe — die dient op web nu de video-embed; (2) een mislukte scriptlading wordt niet meer permanent onthouden.Poorten
make checkgroen (na rebase op de nieuwste main),make check-secretsschoon,make sast0 findings. DAST n.v.t. (geen serveroppervlak geraakt).Bewaker
Geen wijziging aan bestandsformaat, opslag of afhankelijkheid, en geen nieuwe vertrouwde partij (de mermaid-bundel was al gebundeld en in gebruik). De trust-boundary-verschuiving is door de security-architect gewogen; een aparte bewakersronde was niet nodig.