# pWhois Maps — Third-Party Dependencies

**Last reviewed:** 2026-10-05
**Companion document:** [`UPGRADES.md`](UPGRADES.md) — review cadence + upgrade procedure
**Legal basis:** `docs/research/legal-licensing-memo.md` (attribution text in section 4 (superseded for routing data: Maps uses Prefix WhoIs only), component table in section 2, must-not list in section 5)
**Self-hosted-by-policy:** every browser dependency below is bundled in this repository and served from `pwhois.org`. Zero CDN load. Zero third-party script, style, font or image requests. The single permitted external runtime load on the site is VOSTROM's own `https://vostrom.com/vouch/public/vouch.js`. Self-hosting freezes us on whatever we bundle, so `UPGRADES.md` defines the deliberate review cadence.
**Served copy:** this file is duplicated at `web/maps/licenses/THIRD_PARTY.md` (served at `/maps/licenses/THIRD_PARTY.md`) because MIT/ISC/BSD/Apache terms require the notices to accompany the copies we serve. Keep both copies identical (`cmp THIRD_PARTY.md web/maps/licenses/THIRD_PARTY.md`).

Format per row: name, bundled version, license, where in the tree, upstream URL, why we depend on it, CVE-watch URL, last bumped here.

Rule: vendored files are byte-for-byte upstream distribution files. Never re-minify, strip `/*! */` comments or patch them. Verify with the SHA-256 column.

---

## Tier 1 — Browser libraries (vendored under `web/assets/vendor/`)

| Library | Bundled | License | Path | Upstream | Purpose | CVE watch | Last bumped |
|---|---|---|---|---|---|---|---|
| **d3** | 7.9.0 | ISC | `web/assets/vendor/d3.v7.min.js` | https://d3js.org (npm `d3@7.9.0`, file `dist/d3.min.js`) | force layout, scales, SVG selections for the galaxy and the AS graph renderer | https://github.com/d3/d3/security/advisories | 2026-10-05 |
| **mermaid** | 11.17.2 | MIT | `web/assets/vendor/mermaid.min.js` | https://mermaid.js.org (npm `mermaid@11.17.2`, file `dist/mermaid.min.js`, IIFE exposing `globalThis.mermaid`) | lazy-loaded live preview of exported Mermaid diagrams (design canvas, "Make it yours") | https://github.com/mermaid-js/mermaid/security/advisories | 2026-10-05 |
| **Viz.js** (`@viz-js/viz`) | 3.31.0 | MIT (wrapper) + EPL-2.0 (Graphviz) + MIT (Expat) | `web/assets/vendor/viz-standalone.js` | https://github.com/mdaines/viz-js (npm `@viz-js/viz@3.31.0`, file `dist/viz-global.js`, UMD exposing `Viz`; WebAssembly is embedded in the file, no separate `.wasm`) | lazy-loaded Graphviz (WASM) for DOT preview and layouts in the design canvas | https://github.com/mdaines/viz-js/security/advisories and https://gitlab.com/graphviz/graphviz/-/issues (security label) | 2026-10-05 |

Integrity (computed after copying into the tree):

| File | Version | Bytes | SHA-256 |
|---|---|---:|---|
| `web/assets/vendor/d3.v7.min.js` | 7.9.0 | 279,706 | `f2094bbf6141b359722c4fe454eb6c4b0f0e42cc10cc7af921fc158fceb86539` |
| `web/assets/vendor/mermaid.min.js` | 11.17.2 | 3,572,661 | `581ed7d74bd9048d0e3a91363927d72ef22942d7722546b27f7cc29e35390eb8` |
| `web/assets/vendor/viz-standalone.js` | 3.31.0 | 1,329,882 | `c9e0b310f9883910e01c66054b48b7ff4be3d8695141116635e72b0af152692e` |

npm tarball integrity (SRI sha512, as published by the registry and re-verified locally before extraction):

| Tarball | Integrity |
|---|---|
| `d3-7.9.0.tgz` | `sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==` |
| `mermaid-11.17.2.tgz` | `sha512-V6K3C8EBdEsPFZXSKMJe6ppQOENxuHARr9GvHX4hh47lAbhMRD9qf4oEK7LoaRQxULMa80/qt5gHO73aCleBBg==` |
| `viz-3.31.0.tgz` (`@viz-js/viz`) | `sha512-r7zlQdRvcwvIpjHGgs+KNWHeE/P5/Dq7k8ZAKaMCbZqomxCBJV78gVuQYaHzFVca+kB0mX0fMW9UFevCOBG50A==` |

### Why mermaid 11.17.2 and not the latest 12.x

`mermaid@12.1.0` (`latest` on npm at 2026-10-05) ships `dist/mermaid.min.js` as a plain IIFE with the trailing `/*! Bundled license information */` block, but it **bundles elkjs (Eclipse Layout Kernel, EPL-2.0) inside the file without any EPL notice** (`mermaid@12.0.0` does too). Serving it would make the site a Distributor of a second EPL-2.0 program in object form, and would contradict memo section 5 item 1 ("do not load layout-elk"). `mermaid@11.17.2` (newest 11.x) is the same IIFE shape, has no elkjs, and keeps the `/*! Bundled license information */` blocks (lodash-es, DOMPurify, cytoscape parts). Revisit when a 12.x release stops bundling elkjs or ships its notice (see `UPGRADES.md`).

### Graphviz / Expat inside `viz-standalone.js`

- Graphviz **16.1.0** (build 20260904.0139): confirmed three ways — `Viz.graphvizVersion === "16.1.0"`, the SVG comment emitted by a test render, and `lib/metadata.js` in the package. EPL-2.0 (since Graphviz 15.0.0).
- Expat **2.8.5**: from the build-provenance attestation shipped in the npm package (`lib/provenance.json`). MIT.
- Build provenance (same file): viz-js repository revision `c8ce050d28eb0dc1ed1629ea32ab7f3dc117db0f`, `packages/viz/backend`; Graphviz source tarball SHA-256 `beea483ab130f456c1c3905f4f2e40778a9c493c3d73ae8012367d552d71ca84` and Expat tarball SHA-256 `920dde485e15eda0cce8d2310b41d492c534e5e3d89ad407a0b4176dd2ff88fe` — both re-computed locally against fresh downloads on 2026-10-05 and matched.
- EPL-2.0 obligations met: license text at `/maps/licenses/EPL-2.0.txt`; Source Code statement at `/maps/licenses/graphviz-source.txt` and on `/maps/credits.who`; upstream header in `viz-standalone.js` preserved; no modifications.
- We do **not** self-host the 26.8 MB Graphviz source tarball; the statement points to the durable upstream release URL and tag (memo 3.4 recommends self-hosting; counsel item 6 asks whether a durable link suffices). To self-host later: download the tarball, verify the SHA-256 above, place it at `web/maps/licenses/graphviz-16.1.0-source.tar.gz` and add the path to `graphviz-source.txt` and `credits.who`.

---

## Tier 2 — Components bundled inside the vendored files (notices stripped by minification; reproduced here and on `/maps/credits.who`)

### Inside `mermaid.min.js` 11.17.2 (dependencies declared in the package; license per npm registry metadata)

| Component | License | Notes |
|---|---|---|
| d3 (and its d3-* modules) | ISC (d3-ease: BSD-3-Clause) | Copyright 2010-2023 Mike Bostock; d3-ease also Copyright 2001 Robert Penner. Texts: `ISC-d3.txt`, `BSD-3-d3-ease.txt` |
| d3-sankey | BSD-3-Clause | Copyright 2015, Mike Bostock. Text: `BSD-3-d3-sankey.txt` |
| dagre-d3-es | MIT | |
| cytoscape | MIT | Copyright (c) 2016-2024 The Cytoscape Consortium; embedded notices for Promises/A+ thenable (Ralf S. Engelschall), jQuery-style events, Bezier generator (Gaetan Renaudeau), spring physics (Koen Bok) are retained in the trailing license block |
| cytoscape-fcose | MIT | Copyright (c) 2018-present iVis-at-Bilkent |
| cytoscape-cose-bilkent | MIT | |
| DOMPurify 3.4.12 | MPL-2.0 OR Apache-2.0 | **Election: Apache-2.0** (`Apache-2.0.txt`); header retained in the trailing license block |
| KaTeX | MIT | Copyright (c) 2013-2020 Khan Academy and other contributors |
| khroma | MIT | registry `license` field is empty; upstream repository license is MIT (verify at next review) |
| roughjs | MIT | Copyright (c) 2019 Preet Shihn |
| Langium (+ vscode-languageserver pieces) | MIT | via `@mermaid-js/parser` |
| Chevrotain (+ chevrotain-allstar) | Apache-2.0 (Chevrotain), MIT (allstar) | via Langium; text: `Apache-2.0.txt` |
| lodash-es | MIT | Copyright OpenJS Foundation and other contributors; header retained |
| marked, stylis, dayjs, uuid, @braintree/sanitize-url, @iconify/utils, @upsetjs/venn.js, es-toolkit, fastdom, ts-dedent | MIT | |

Not included: `elkjs` / `@mermaid-js/layout-elk` (EPL-2.0). Do not add it.

### Inside `d3.v7.min.js` 7.9.0

d3 7.9.0 bundles its d3-* modules (ISC, except d3-ease BSD-3-Clause), delaunator (ISC, Copyright 2018 Vladimir Agafonkin; header retained in the unminified file) and robust-predicates (Unlicense). d3-scale-chromatic carries ColorBrewer color schemes (Apache-2.0, Cynthia Brewer) — text: `Apache-2.0.txt`.

License files served at `/maps/licenses/`: `EPL-2.0.txt`, `Apache-2.0.txt`, `ISC-d3.txt`, `MIT-mermaid.txt`, `MIT-viz.txt`, `MIT-expat.txt`, `BSD-3-d3-sankey.txt`, `BSD-3-d3-ease.txt`, `OFL-1.1.txt`, `graphviz-source.txt`. Source of each text: upstream repository / registry package (d3 and mermaid from the npm tarballs; Viz.js from `mdaines/viz-js@v3`; Expat from `libexpat@R_2_8_5`; d3-sankey and d3-ease from `d3/*` default branches; EPL-2.0 from `eclipse.org/org/documents/epl-2.0/EPL-2.0.txt`, byte-identical to the Graphviz 16.1.0 `LICENSE`; Apache-2.0 from `apache.org/licenses/LICENSE-2.0.txt`; OFL texts from the JetBrains Mono and Nunito Sans repositories).

---

## Tier 3 — Fonts (pre-existing; self-hosted)

| Font | License | Path | Upstream | Notes |
|---|---|---|---|---|
| **JetBrains Mono** (variable) | OFL-1.1 | `web/assets/fonts/JetBrainsMono-var.woff2` (14,204 B, SHA-256 `c55888bfe44fb6e39b0b0c3d50dcf79ee971ef4181810d1ead0943bf57e9f2e8`) | https://github.com/JetBrains/JetBrainsMono | Copyright 2020 The JetBrains Mono Project Authors. OFL text beside the fonts at `web/assets/fonts/LICENSE.txt`; copy at `/maps/licenses/OFL-1.1.txt` |
| **Nunito Sans** (variable) | OFL-1.1 | `web/assets/fonts/NunitoSans-var2.woff2` (25,344 B, SHA-256 `fa2e924b77e3659a5d751a51e38e38fcae2290fe6bd2ba7cf5f725cfa5827c48`) | https://github.com/Fonthausen/NunitoSans | Copyright 2016 The Nunito Sans Project Authors; no reserved font names declared |

---

## Tier 4 — Data sources (NOT bundled; displayed with attribution on `/maps/credits.who`)

| Source | Terms | What we do | Risk (memo) |
|---|---|---|---|
| **Prefix WhoIs** (`whois.pwhois.org:43`) | VOSTROM's own service; table built from VOSTROM's live BGP sessions and route-views digests | the ONLY routing-data source for Maps; queried through a fixed whitelist of query shapes; Next-Hop and Router-ID are never emitted; attribution `Data: Prefix WhoIs (pwhois.org)` | n/a |
| **Regional registries** (ARIN, RIPE NCC, APNIC, LACNIC, AFRINIC) | compiled by pWhois under its agreements with each registry; the map does not query any RIR directly; copyright and database rights remain with the registries | organisation and network names shown with the credits-page paragraph (network operations and research use; no advertising, direct marketing or marketing research) | covered by pWhois's registry agreements (per VOSTROM) |
| **Geolocation** (city, region, country, coordinates shown for a prefix) | community-sourced; not attributed to any third party | shown with a disclaimer on `credits.who`: no accuracy guarantee, not to be relied on for anything requiring precision | n/a |

Not used by Maps (no direct RouteViews or RIPE RIS feed; RIS may become an optional labelled source later, never default): PeeringDB (not CC0), CAIDA AS Rank / AS Relationships, bgp.he.net and bgpmap.net scraping, Twemoji, `@mermaid-js/layout-elk` / elkjs.

---

## Tier 5 — System runtime (NOT bundled)

| Component | Version | License | Notes |
|---|---|---|---|
| **PHP** | 8.1 (production host) | PHP License v3.01 | no Composer packages; stdlib + PDO SQLite only |
| **SQLite** | system library via PDO | public domain | stores quota, cache and audit data for Maps |

---

## What we do NOT depend on (and why)

- **No package manager at runtime** — no `composer.json`, no `package.json`, no `node_modules` in the deployed tree. npm tarballs are fetched once, inspected, and the single distribution file is copied in.
- **No CDN scripts** — `<script>`, `<link>` and `fetch()` only point at `pwhois.org` (and VOSTROM's Vouch script). Mermaid and Graphviz load lazily from `/assets/vendor/`; Viz.js has the WASM embedded so it makes no extra request.
- **No build step** — vendored files are served exactly as published.
