1# Renderer extraction for diagram.zip23## Status45The repository assigns a final renderer path to all 30 catalog engines. The application does not contain a Fly.io render fallback. The catalog Worker does not contain a render proxy.67Production rollout requires these final checks:891. Deploy the native BPMN, Excalidraw, and TikZ Workers.102. Deploy the private Browser Run bridge and the Mermaid and diagrams.net public units.113. Deploy the catalog Worker, application, and documentation.124. Run the 30-engine production smoke test.1314Pixel comparison is not a completion gate. Structural coverage is the completion gate. Each known loss must be visible in the catalog.1516## Product requirements1718- The product does not require an account.19- Each diagram type remains available.20- Each engine has one selected renderer path.21- A renderer failure must not select another renderer.22- A browser-only renderer must execute behind the private Browser Run service.23- An HTTP renderer must accept only its assigned engine hostname.24- A render result must use the standard SVG viewer contract.25- A renderer must not add engine-specific application UI.26- A renderer must not load remote or filesystem resources unless the unit contract permits them.27- A saved render must record the unit, build, and pipeline.2829## Runtime selection3031Use the closest maintained implementation in this order:32331. Use the official browser implementation.342. Use a JavaScript or TypeScript library in a Worker.353. Use the maintained Python library in a Python Worker.364. Use a precompiled WebAssembly module in a Worker.375. Translate a bounded source language into a migrated engine.3839Do not keep a compatibility service after an engine has a final path.4041## Final topology4243```text44diagram.zip application45 |- HTTP renderer at {engine}.render.diagram.zip/v1/svg46 |- persistence Worker at diagram.zip/api/v1/*47 `- catalog Worker at diagram.zip/render/v1/{health|catalog}4849Mermaid/diagrams.net HTTP unit50 `- private Browser Run service binding51 `- pinned renderer frame52```5354The catalog Worker does not render diagrams. `POST /render/v1/svg` returns `404`.5556Each engine has a public renderer hostname. Engines can share one Worker deployment when they have the same dependencies and failure boundary. The request body does not select an engine.5758## Engine inventory5960| Engine | Runtime | Unit or pipeline |61| --- | --- | --- |62| PlantUML | Worker WebAssembly | `plantuml-family` |63| Mermaid | Browser Run | `mermaid` through the private Browser Run bridge |64| GraphViz | Worker WebAssembly | `graphviz-family` |65| D2 | Worker WebAssembly | `d2` with the bounded grid layout |66| C4 PlantUML | Worker WebAssembly | `plantuml-family` through the C4 lowerer |67| BlockDiag | Worker Python | `blockdiag-family` |68| SeqDiag | Worker Python | `blockdiag-family` |69| ActDiag | Worker Python | `blockdiag-family` |70| NwDiag | Worker Python | `blockdiag-family` |71| PacketDiag | Worker Python | `blockdiag-family` |72| RackDiag | Worker Python | `blockdiag-family` |73| BPMN | Worker JavaScript | `bpmn` bounded BPMN DI-to-SVG renderer |74| Bytefield | Worker JavaScript | `bytefield` |75| DBML | Worker WebAssembly | `graphviz-family,dbml,graphviz` |76| diagrams.net | Browser Run | `diagramsnet` through the private Browser Run bridge |77| Ditaa | Worker WebAssembly | `svgbob-family,svgbob` |78| ERD | Worker WebAssembly | `graphviz-family,erd,graphviz` |79| Excalidraw | Worker JavaScript | `excalidraw` with a Worker DOM/canvas shim |80| GoAT | Worker WebAssembly | `goat` |81| Nomnoml | Worker JavaScript | `nomnoml` |82| Pikchr | Worker WebAssembly | `pikchr` |83| Structurizr | Worker JavaScript and WebAssembly | `structurizr,plantuml-family,plantuml` |84| Svgbob | Worker WebAssembly | `svgbob-family` |85| Symbolator | Worker Python | `symbolator` |86| TikZ | Worker WebAssembly | `tikz` with the bundled TikZJax TeX core |87| UMLet | Worker JavaScript | `umlet` UXF-to-SVG translator |88| Vega | Worker JavaScript | `vega-family` |89| Vega-Lite | Worker JavaScript | `vega-family,vega` |90| WaveDrom | Worker JavaScript | `wavedrom` |91| WireViz | Worker Python and WebAssembly | `wireviz,graphviz-family,graphviz` |9293## Dependency groups9495The BlockDiag family shares Python, Pillow, fonts, plugins, and renderer registration. It uses one Worker deployment and six hostnames.9697The GraphViz family shares one precompiled GraphViz module. GraphViz, DBML, and ERD use the same deployment. WireViz calls this deployment through a service binding.9899The PlantUML family shares one PlantUML runtime. C4 PlantUML lowers a bounded C4 macro set into PlantUML.100101The Svgbob family shares one precompiled Svgbob module. Ditaa lowers bounded ASCII input into Svgbob input.102103The Vega family shares the Vega runtime. Vega-Lite compiles into Vega.104105Other engines use separate units because they do not share a runtime or failure boundary.106107## HTTP unit contract108109An HTTP unit provides these routes:110111- `GET /v1/health`112- `GET /v1/capabilities`113- `POST /v1/svg`114115The POST body has this form:116117```ts118interface UnitRenderRequest {119 source: string;120 format: "svg";121 options: Record<string, string>;122 metadata: {123 title: string;124 description: string;125 };126 presentation: {127 background: string;128 padding: number;129 frame: boolean;130 };131}132```133134The body does not contain an engine field. The hostname selects the engine.135136The response contains these identity headers:137138- `X-Diagram-Engine`139- `X-Diagram-Unit`140- `X-Diagram-Pipeline`141- `X-Diagram-Renderer`142- `X-Renderer-Build`143144## Browser Run contract145146A browser-backed public unit provides the standard HTTP routes and calls the private Browser Run Worker through a service binding. The private service keeps a serialized Durable Object session for each engine and has no public route.147148The Browser Run page loads the pinned engine frame and uses the `diagram.zip:renderer:v1` message protocol internally. The frame returns an SVG result to the private service; the public unit canonicalizes it before responding.149150The application sees only the public HTTP contract. It does not create renderer iframes or execute renderer packages.151152## Presentation and SVG policy153154Base rendering and presentation are separate stages:155156```text157validate -> render base SVG -> sanitize -> decorate -> sanitize -> respond158```159160The presentation stage can add a title, description, canvas background, padding, and frame. It must not replace renderer colors.161162The sanitizer removes scripts, event handlers, active embedded HTML, and external resources. A unit must reject unsafe source features before rendering when the underlying engine can load resources.163164## Coverage policy165166The migration uses structural checks. Each engine must meet these requirements:167168- The final HTTP route is available.169- The repository fixture returns SVG.170- The SVG has usable dimensions.171- The response identifies the expected unit and pipeline.172- The output does not contain prohibited active content.173- A documented renderer feature is not silently removed.174175The migration does not require pixel equality with the Docker image. Docker remains available for bounded reference checks. Java reference checks must run in Docker.176177## Known loss policy178179Each loss belongs to one engine catalog entry. The unit capabilities response must return the same loss list.180181Examples include these losses:182183- D2 uses the bounded grid layout. Dagre and ELK are not available in the Worker.184- Ditaa uses a bounded translation into Svgbob. Some Ditaa shapes and styles are not retained.185- UMLet uses browser-independent text metrics. Unknown custom Java elements become labeled generic boxes.186- TikZ uses the bundled TikZJax package set. It does not use a complete TeX Live installation.187- GraphViz rejects external image and filesystem options.188- PlantUML rejects remote includes, filesystem includes, and arbitrary theme directives.189- Symbolator uses deterministic SVG text estimates instead of Cairo and Pango.190191A loss must not trigger a request to Fly.io. A loss must not select a different engine without an explicit translation pipeline.192193## UMLet boundary194195UMLet accepts UXF and returns ordinary SVG. It does not load UMLetino or a UMLet user interface.196197The repository fixture uses these custom elements:198199- `com.umlet.element.custom.State`200- `com.umlet.element.custom.InitialState`201- `com.umlet.element.custom.FinalState`202- `com.umlet.element.custom.HistoryState`203- `com.umlet.element.custom.ThreeWayRelation`204205The translator handles all five elements directly. An unknown custom Java class becomes a labeled generic box. The translator does not execute custom Java code.206207## TikZ boundary208209TikZ runs in a dedicated WebAssembly Worker with the pinned TikZJax TeX/PGF package set. Wrangler imports the TeX module through its `CompiledWasm` rule. Each serialized request streams the compressed format dump directly into fresh Wasm memory.210211The unit cannot load arbitrary packages or external files. Its deterministic extraction script, unmodified corresponding TikZJax source, provenance, and GPL/LPPL terms are stored with the artifact.212213## Fly.io removal boundary214215DiagramZip runs on Cloudflare and the repository contains no Fly.io application or renderer configuration. Fly.io is not a runtime, deployment, or fallback dependency.216217The renderer extraction is complete only when all of these statements are true:218219- The application has no `/render/v1/svg` request path.220- The catalog Worker has no `POST /render/v1/svg` implementation.221- The repository has no origin adapter.222- The repository has no compatibility unit.223- The renderer catalog has no `origin` runtime.224- All 30 engines pass the production route audit.225226## Deployment and rollback227228Deploy each final unit before the application cutover. Then deploy the catalog Worker, application, and documentation.229230Rollback uses a prior version of the same final unit. Rollback does not restore the Fly.io render fallback.231232## Completion checks233234Run these checks before completion:2352361. Run all renderer tests.2372. Run all application tests.2383. Run all documentation tests and the production build.2394. Run Wrangler dry-runs for every Worker unit.2405. Run build and protocol checks for the Browser Run bridge and both browser-backed units.2416. Search the application and renderer code for origin and compatibility paths.2427. Deploy the final units.2438. Run the 30-engine production smoke test.2449. Confirm that `POST https://diagram.zip/render/v1/svg` returns `404`.24510. Confirm that the application and documentation examples use direct HTTP units only.