# Exact upstream source and build recipe

This is a source-inspected recipe, not a claim that the upstream WASM build
has been executed or reproduced bit-for-bit. All three complete source archives
are available from the pinned official locations and the source mirror.

## Frozen inputs

- Viz.js 3.31.0 repository commit:
  c8ce050d28eb0dc1ed1629ea32ab7f3dc117db0f.
- Graphviz 16.1.0 release, repository commit:
  e41c710710be080ad37af1b51c6e2f8beffa9ee5.
- Expat 2.8.5 release, repository commit:
  4b3f0b06f39fb5529cead381694f8929901bc273.
- Upstream backend Dockerfile: emscripten/emsdk:6.0.10 in both build stages.

Archive filenames, byte lengths and compressed hashes are in source-manifest.json.
Graphviz's original gzip SHA-256 is
beea483ab130f456c1c3905f4f2e40778a9c493c3d73ae8012367d552d71ca84.
Its prepared xz SHA-256 is
cd31994930c198f77ac2297453e8fadd46556d4d99c198f2d60e4793cb1c2690.
Both decompress to the same 65751040-byte complete tar, SHA-256
b3e0f2a911b6f50f4b7e474b79a24104129bb7ef3f563eb8ac1407e2738fae1c.
The xz change is transport recompression, not editing Graphviz source.

## Upstream procedure

In a fresh scratch checkout extracted from the complete Viz source archive:

1. Use the preserved root package.json and package-lock.json, review the
   scripts, then install pinned build dependencies with npm ci --ignore-scripts.
2. Review packages/viz/Makefile and backend/Dockerfile. Exact text copies
   accompany this document under build-recipe/; files.json records the
   original controls and source hashes.
3. With an already available, separately approved Docker/Emscripten toolchain,
   run make -C packages/viz. The upstream all target builds lib/backend.js,
   generates lib/metadata.js, and runs Rollup to create dist/viz.js,
   dist/viz.cjs and dist/viz-global.js.
4. The original Dockerfile downloads official Graphviz and Expat gzip archives.
   To use the prepared local source mirror instead, apply the two ADD-to-COPY
   edits recorded in build-recipe/local-source-mirror.patch.txt. Put the
   verified Expat gzip into backend/expat.tar.gz. Decompress the Graphviz xz
   stream and gzip the identical tar stream into backend/graphviz.tar.gz,
   without extracting/recreating the tar:
   xz -dc "graphviz-16.1.0.tar.xz" | gzip -n > "graphviz.tar.gz"
   Run this only in a fresh scratch location with shell pipeline failure
   checking enabled and without overwriting existing files. This regenerated
   gzip need not equal the original gzip hash; its DECOMPRESSED TAR hash
   must equal the manifest. Archive/source content is unchanged.
5. This mirror adaptation changes the build recipe, not the library source.
   Keep this patch and its 2026-10-07 preparation date with any such build.
   Build only in scratch space: the Makefile's clean target removes outputs.
6. Record actual compiler/platform/image digest and validate metadata,
   layouts, HTML labels and SVG output. No bit-identical-build claim is made.

The inspected recipe builds Expat statically, disables Graphviz ltdl, and
links gvplugin_dot_layout, gvplugin_neato_layout, gvplugin_core, gvc,
pathplan, cgraph, xdot, cdt and expat. It uses -Oz, SINGLE_FILE=1,
MODULARIZE=1, EXPORT_ES6=1, ENVIRONMENT=web, and the exact remaining flags
in Dockerfile.txt. Do not silently substitute a different library/plugin set.

A separately resolved CURRENT emsdk:6.0.10 image index digest is
sha256:e077d54e2b8970575ebc4f185ac1de0b95c05f2b266134d4ba27449af7aebf65.
This is not proof of the image digest used by the upstream npm release job.
No image was pulled or run in this review.

## Application build is a separate layer

The product source/ directory supplies its independent npm lock and rebuild
tool. Its clean application rebuild must use the actual recorded build
definitions, including production NODE_ENV where required. Installing
@viz-js/viz's prebuilt npm module is not rebuilding Graphviz/Expat/WASM.
Final package manifests must bind the correct application/source/lock hashes
and preserve both the original-code MIT and applicable third-party notices.
