Dependencies and licences
This page lists every npm dependency and development dependency, the browser engines served from public/vendor/, code and data ported from third-party projects, the fonts and other assets, and the build-time Python, R and Blender tools, each with its licence as the repository records it. It also documents the licence check in scripts/licences.mjs, the notices file written by scripts/notices.mjs, the exceptions held for the General Counsel, and what the current state would mean for commercial shipping.
Current state, as checked on 10 October 2026
Two commands were run in the repository with node_modules installed:
npm ls --depth=0 exited 0 and listed the 26 direct packages at the versions in the tables below. It also listed six packages as extraneous: @emnapi/core@1.10.0, @emnapi/runtime@1.11.3, @emnapi/wasi-threads@1.2.1, @img/sharp-wasm32@0.35.5, @napi-rs/wasm-runtime@1.2.2 and @tybys/wasm-util@0.10.3. They are installed but not reachable from package.json on this platform. In package-lock.json, @img/sharp-wasm32 is an optional dependency of @img/sharp-freebsd-wasm32 and @img/sharp-webcontainers-wasm32, both platform-restricted. Its declared licence is Apache-2.0 AND LGPL-3.0-or-later AND MIT.
node scripts/licences.mjs --json exited 0 with "findings": []. Its summary:
| Part | Result |
|---|---|
| Production closure | 259 packages; 3 by exception: @img/sharp-libvips-linux-x64@1.3.4, @img/sharp-libvips-linuxmusl-x64@1.3.4, caniuse-lite@1.0.30001806 |
| Development closure | 345 packages; reported, not refused: axe-core@4.12.1 (MPL-2.0), caniuse-lite@1.0.30001806 (CC-BY-4.0), lightningcss@1.32.0, lightningcss-linux-x64-gnu@1.32.0 and lightningcss-linux-x64-musl@1.32.0 (MPL-2.0), minimatch@10.2.6 (BlueOak-1.0.0) |
| Vendored browser builds | 3 |
| GPL or academic-only tools named in the registry | Blender 5.2 (bpy 5.2.2) and Molecular Nodes (Cell, build-time); primer3-py 2.3.1 (Sequence, oracle); R 4.3.3, drc 4.0-0 and MASS 7.3-60.0.1, and R 4.4.3 in the oracle image for the 0.5.0 cross-checks (Assay, oracles) |
Licence distribution of the production closure, computed with the script's own walkClosure("dependencies"): MIT 230, Apache-2.0 10, ISC 7, BSD-3-Clause 5, LGPL-3.0-or-later 2, (MIT AND Zlib) 2 (pako 2.2.0 via 3dmol, and pako 1.0.11 via upng-js, itself a 3dmol dependency), Python-2.0 1 (argparse 2.0.1 via molstar and js-yaml), CC-BY-4.0 1 (caniuse-lite, via next and browserslist), 0BSD 1 (tslib 2.8.1).
The development closure: MIT 291, Apache-2.0 22, ISC 15, BSD-2-Clause 7, MPL-2.0 4, BSD-3-Clause 2, Python-2.0 1, CC-BY-4.0 1, CC0-1.0 1, BlueOak-1.0.0 1.
The production closure counts every package reachable from dependencies, not only code that reaches the browser. For example, molstar declares express, compression, cors, swagger-ui-dist, h264-mp4-encoder, react-markdown and others for its own command-line and server tools. The suite serves only Mol*'s prebuilt viewer, but those packages are walked, checked and listed in the notices file.
Runtime dependencies
package.json dependencies, with the installed version, the licence declared in the package's package.json, and where the code uses it.
| Package | Range in package.json |
Installed | Licence | Purpose | Where used | Reaches the browser |
|---|---|---|---|---|---|---|
next |
16.3.8 |
16.3.8 | MIT | Framework, build, routing, next/font, next/og, image optimisation |
Whole app | Yes |
react, react-dom |
19.2.8 |
19.2.8 | MIT | UI | Whole app | Yes |
@floating-ui/dom |
1.8.0 |
1.8.0 | MIT | Positioning of popovers and menus | src/components/suite/overlay/floating.ts |
Yes |
@rdkit/rdkit |
2026.3.6 |
2026.03.6 | BSD-3-Clause | RDKit.js WebAssembly chemistry engine | Served from public/vendor/rdkit@2026.3.6/ and loaded with importScripts in src/components/suite/engines/rdkit/rdkit.worker.ts; client code imports only its types; Node tests and src/apps/education/experiments/applied/build-molecules.mjs load the package directly |
Yes, as a vendored build |
molstar |
5.11.0 |
5.11.0 | MIT | Mol* 3D viewer | Served from public/vendor/molstar@5.11.0/; loaded by src/components/tools/protein-explorer/molstar-view.tsx and src/components/tools/inside-a-cell/molstar-viewer.tsx |
Yes, as a vendored build |
3dmol |
2.5.5 |
2.5.5 | BSD-3-Clause | 3Dmol.js conformer viewer | Served from public/vendor/3dmol@2.5.5/; loaded by src/apps/molecule-workbench/panels/shape-panel.tsx |
Yes, as a vendored build |
openchemlib |
9.25.0 |
9.25.0 | BSD-3-Clause | Structure editor, conformers, MMFF94s+ | Dynamic import("openchemlib") in src/components/tools/molecule-workbench/structure-editor.tsx; conformer.worker.ts; the developer kit |
Yes, bundled |
uqr |
0.1.3 |
0.1.3 | MIT | QR codes as inline SVG | src/components/tools/lab-calculators/panels/label-dialog.tsx |
Yes, bundled |
fuse.js |
7.5.0 |
7.5.0 | Apache-2.0 | Fuzzy matching | src/lib/literature/search/concepts.ts, saved-papers.ts |
Yes, bundled |
fast-xml-parser |
5.11.2 |
5.11.2 | MIT | Europe PMC full-text XML; the .pzfx project file in Assay's Import | src/lib/literature/fulltext.ts; src/lib/grid/pzfx.ts |
Server for literature; in the browser for Assay, loaded on demand when a .pzfx file is chosen |
marked |
18.0.14 |
18.0.14 | MIT | Rendering the technical documentation | src/lib/technical-docs/render.ts |
No (server) |
@supabase/ssr |
^0.12.7 |
0.12.7 | MIT | Account sessions with cookies | src/lib/workspace/server.ts |
No (server) |
@supabase/supabase-js |
^2.117.2 |
2.117.2 | MIT | Service-role client | src/lib/workspace/server.ts |
No (server) |
stripe |
^23.0.0 |
23.0.0 | MIT | Billing | src/lib/workspace/billing.ts, src/app/api/workspace/billing/checkout/route.ts |
No (server) |
server-only |
^0.0.1 |
0.0.1 | MIT | Build fails if a server module is imported by a client component | Imported by src/lib/workspace/server.ts, billing.ts, src/lib/search/catalog-server.ts, src/lib/technical-docs/load.ts, src/components/suite/marketing/landing-education.marketing.tsx |
No |
Notable transitive packages: sharp 0.35.5 (Apache-2.0, an optional dependency of next) with its platform binaries @img/sharp-linux-x64 and @img/sharp-linuxmusl-x64 (Apache-2.0) and the libvips binaries @img/sharp-libvips-* (LGPL-3.0-or-later). These serve Next's image optimisation, which the suite uses through next/image (for example src/components/tools/inside-a-cell/still.ts and src/components/suite/marketing/poster.marketing.tsx).
Development dependencies
| Package | Range | Installed | Licence | Purpose |
|---|---|---|---|---|
@playwright/test |
1.56.1 |
1.56.1 | Apache-2.0 | Browser tests under e2e/ |
axe-core |
4.12.1 |
4.12.1 | MPL-2.0 | Accessibility checks injected by e2e/support/axe.ts |
eslint |
^9 |
9.39.5 | MIT | Linting |
eslint-config-next |
16.3.8 |
16.3.8 | MIT | Next's lint rules |
typescript |
^5 |
5.9.3 | Apache-2.0 | Type checking (npx tsc --noEmit) |
tailwindcss |
^4 |
4.3.3 | MIT | CSS |
@tailwindcss/postcss |
^4 |
4.3.3 | MIT | PostCSS plugin; brings lightningcss (MPL-2.0) |
@types/node |
^20 |
20.19.43 | MIT | Node types |
@types/react |
^19 |
19.2.18 | MIT | React types |
@types/react-dom |
^19 |
19.2.4 | MIT | React DOM types |
The development tools never ship. Tailwind's output is CSS the suite writes from its own classes; lightningcss runs at build time.
Version pinning policy
What the repository does, as found:
- Twelve of the sixteen runtime dependencies are pinned to an exact version. The four with caret ranges are
@supabase/ssr,@supabase/supabase-js,server-onlyandstripe. Of the development dependencies,@playwright/test,axe-coreandeslint-config-nextare exact; the rest use caret ranges. package-lock.json(lockfile version 3) fixes every installed version. Every GitHub workflow installs withnpm ci. There is no.npmrcand no Dependabot or Renovate configuration.- The three vendored engines must be pinned exactly:
scripts/vendor.mjsthrows "pin <pkg> to an exact version in package.json" otherwise, andsrc/lib/vendor.test.tsasserts thatvendorVersionsinsrc/lib/vendor.tsequals thepackage.jsonpins. Since Wave 4,bundledVersionsin the same file records OpenChemLib (9.25.0), which is bundled rather than vendored; the test checks it againstpackage.json, the installed package, OpenChemLib's runtimeversionand every "OpenChemLib JS x.y.z" incontent/tools/molecule-workbench.ts.RDKIT_VERSION(src/components/tools/molecule-workbench/versions.ts) is checked againstvendorVersionsbypolicy.test.ts. The version is part of the served path (/vendor/<name>@<version>/), so a new release is a new URL and can be cached as immutable. EXCEPTIONSinscripts/licences.mjsis keyed byname@version. A version change of an excepted package makes the check report the new version as not on the allow-list, and the old key as "an exception names a package that is not installed; remove it" (unless the old key is an optional package for another platform in the lockfile).caniuse-litechanges version often, so updatingnextorbrowserslistusually needs this entry updated.engines.nodeis>=22.18and.nvmrcis22.18, while@types/nodeis^20.
When an engine version changes, these places name the version in text and are not checked against package.json by any test found: the registry source names (Mol* 5.11.0 in content/apps/protein-explorer.ts and content/apps/inside-a-cell.ts, and in the cspAllowances reasons; RDKit and RDKit.js 2026.03.6, 3Dmol.js 2.5.5 in content/apps/molecule-workbench.ts; RDKit.js 2026.03.6 in content/apps/assay-analyser.ts; uqr 0.1.3 in content/apps/lab-calculators.ts); _version in public/data/molecule-workbench/ocl-resources.json; painsSource in src/components/tools/molecule-workbench/pains-data.ts; and the RDKit pin in .github/workflows/scheduled.yml and pipeline/molecule-workbench/rdkit_reference.py, which refuses any other release.
Vendored browser builds
scripts/vendor.mjs exports a packages list and, when run as the main script (npm run vendor, run by predev and prebuild), copies each build and its licence text into public/vendor/<name>@<version>/. It deletes copies of other versions. public/vendor/ is gitignored. Build, test and CI covers the build hook.
| Name | Package | Files copied | Licence text served as LICENSE.txt |
Exposes |
|---|---|---|---|---|
molstar |
molstar |
build/viewer/molstar.js, build/viewer/molstar.css |
The package's LICENSE (MIT, "Copyright (c) 2017 - now, Mol* contributors") |
window.molstar |
rdkit |
@rdkit/rdkit |
dist/RDKit_minimal.js, dist/RDKit_minimal.wasm |
scripts/licenses/rdkit-LICENSE.txt (BSD 3-Clause, Rational Discovery LLC, Greg Landrum, Julie Penzotti and others), because the npm package ships no licence file; the comment says it is copied from the Release_2026_03_6 tag. Also scripts/licenses/inchi-LICENSE.txt, served as INCHI-LICENSE.txt, for the InChI code compiled into the WebAssembly |
initRDKitModule |
3dmol |
3dmol |
build/3Dmol-min.js, build/3Dmol-min.js.LICENSE.txt |
The package's LICENSE (BSD-3-Clause) |
window.$3Dmol |
The paths are built in src/lib/vendor.ts (vendor.molstarJs, vendor.rdkitWasm and so on). The /vendor/:path* header rule caches them as immutable (Security and network). Mol* also needs 'unsafe-eval' and data: in connect-src in the apps that load it; RDKit needs 'wasm-unsafe-eval' (Security and network).
The registry records InChI (MIT, "Copyright (c) 2024 InChI Project") as bundled in RDKit.js (content/apps/molecule-workbench.ts, source inchi). RDKit's Release_2026_03_6 builds it from InChI's v1.07.3 source archive (INCHI-1-SRC.zip, named with its MD5 in RDKit's Code/cmake/Modules/FindInchi.cmake), and the WebAssembly names "InChI version 1, Software 1.07.3 (API Library)". scripts/licenses/inchi-LICENSE.txt holds, verbatim, the repository's LICENSE at tag v1.07.3, the MIT notice in the header of every source file RDKit compiles ("Copyright (c) 2024 IUPAC and InChI Trust") and the separate MIT notice of INCHI_BASE/src/sha2.c (Paul Bakker), each read on 17 October 2026 from the archive whose MD5 matched RDKit's (comment markers removed; the provenance is in BUNDLED_NOTICES in scripts/lib/licence-texts.mjs). The text is served beside the vendored build as INCHI-LICENSE.txt and written into public/third-party-notices.txt. Whether the minimal RDKit build bundles other third-party code with its own notice requirements is not checked by any script.
Third-party code and tables inside the suite's own files
| What | File | Origin and licence as recorded |
|---|---|---|
| QED | src/components/tools/molecule-workbench/qed.ts |
TypeScript port of RDKit's rdkit/Chem/QED.py (Release_2026_03_6). The file keeps Novartis's BSD-3-Clause notice in full. public/tools/molecule-workbench/qed-notice.txt repeats it and is linked from the Molecule source list |
| PAINS filters | src/components/tools/molecule-workbench/pains-data.ts |
Generated by pipeline/molecule-workbench/rdkit_reference.py pains from RDKit's FilterCatalog (Code/GraphMol/FilterCatalog/pains_*.in); header names the RDKit BSD-3-Clause licence and points to /third-party-notices.txt |
| OpenChemLib conformer and MMFF94 tables | public/data/molecule-workbench/ocl-resources.json |
Copied from openchemlib's dist/resources.json by pipeline/molecule-workbench/copy-ocl-resources.mts; _licence: "BSD-3-Clause", _version: "9.25.0", and a _notice naming cheminfo's copyright |
| Genetic code tables | src/lib/seq/codes-data.ts |
Built by pipeline/sequence-toolkit/build-codes.mts from NCBI gc.prt 4.6 (public domain, NCBI) |
| Helvetica, Helvetica-Bold and Symbol widths (Stage A) | src/lib/figure/afm-widths.ts |
Generated by pipeline/assay-analyser/figure/afm_widths.py from Adobe's Core 14 AFM files (Helvetica.afm, Helvetica-Bold.afm, Symbol.afm, 1997), vendored unmodified with Adobe's MustRead.html in pipeline/assay-analyser/figure/afm/ (fetched on 12 October 2026 from the Apache PDFBox repository; SHA-256 in the generated header). MustRead permits use, copying and distribution with or without modification provided the copyright notices are kept, the AFM files travel with it, modifications are noted and its paragraph is unchanged; the generated file repeats the notices and the paragraph verbatim and says what was extracted. Minified bundles drop comments, so the shipped table carries no notice; whether that meets the terms, and "Helvetica" and "Symbol" as names in copy, are held for the General Counsel (CTO's ruling 7). The generator uses pypdf 6.17.0's Adobe Glyph List (BSD-3-Clause) at build time only and cross-checks the widths against pypdf's core-font metrics |
| The viridis colour map (Stage A, the figure editor's heatmaps) | src/lib/figure/viridis.ts |
Generated by pipeline/assay-analyser/figure/viridis_ts.py from pipeline/assay-analyser/fixtures/figure/viridis-table.json: the 256 entries of _viridis_data in matplotlib 3.9.2's lib/matplotlib/_cm_listed.py (fetched 13 October 2026; the file's SHA-256 in the fixture). CC0-1.0: "New matplotlib colormaps by Nathaniel J. Smith, Stefan van der Walt, and (in the case of viridis) Eric Firing ... released under the CC0 license / public domain dedication" (github.com/BIDS/colormap, colormaps.py and LICENSE.txt, read the same day); credit is asked, not required, and is given in the generated file's header |
| BLOSUM62 (Wave 4) | src/lib/protein/align/blosum62.ts |
Generated by pipeline/protein-explorer/blosum62.py from NCBI's BLOSUM62 file (stored with its sha256), checked against Biopython 1.88's copy; no licence recorded; redistribution terms held for the General Counsel (D-0055) |
Engines written from published methods with GPL tools used only as oracles (four-parameter logistic fitting, Tm and secondary structure, restriction digests) are described on Oracles and verification; src/lib/fit/index.ts states that nothing is ported from drc.
The licence check
scripts/licences.mjs is the "dependency-licence test" (design system §11.7; the board memo of 5 October 2026; charter §6). It runs five checks and returns findings; npm run check-licences exits 1 on any. It runs:
- under
npm test, throughscripts/licences.test.mjs(eleven tests, two of which check the notices file's output: see The third-party notices file); - in the CI
checkjob, afternpm testand beforenpm run build; - with
--release, which also measures licence read dates against today (the release gate);--jsonprints findings and the summary.
Check 1: the production closure
walkClosure("dependencies") (in scripts/lib/licence-texts.mjs, shared with the notices writer and re-exported by scripts/licences.mjs) walks package.json dependencies, then each package's dependencies and the optionalDependencies npm installed, Node-style through node_modules, one entry per name@version. For each:
- The licence field must be an SPDX expression that the allow-list satisfies (
spdxSatisfies:ORpasses if any side is allowed,ANDneeds both,WITHis read as its left side, an unparseable expression never passes), or the package must have anEXCEPTIONSentry whoselicenceequals the declared one. - A copyleft licence (
COPYLEFT: GPL, LGPL, AGPL, SSPL, BUSL, EUPL) is never covered for shipped code: its exception must sayserverOnly: true, and if.next/staticexists the check fails when any.jsor.mapfile there containsnode_modules/<name>/. - A licence text must travel with the package: a file named
licence,license,copyingornotice(with optional.md,.txtor.markdown), or aLOCAL_LICENCESentry whose file exists (licenceTextPath, the same lookup the notices writer uses to write the text), unless a server-only exception saystextNotRequired. - Every
EXCEPTIONSkey must be installed, unless the lockfile holds it as an optional package for another platform.
Check 2: the development closure
The same walk over devDependencies. A package fails only if it has no licence field, or a copyleft, UNLICENSED or SEE LICENSE IN licence with no alternative in the allow-list or in MPL-2.0, BlueOak-1.0.0, CC-BY-4.0 or BSD-2-Clause. Other non-allow-listed licences are reported, not refused. Licence texts are not required. The header records the CEO's rule as "nothing GPL in dependencies or devDependencies".
Check 3: the vendored builds
For each entry in scripts/vendor.mjs packages: installed, licence on the allow-list, and each licence text source present.
Check 4: the source scan
Every .ts, .tsx, .mts, .mjs, .js and .json file under src/ and content/ except tests is matched against SOURCE_PATTERNS: GPL licence headers ("GNU General/Lesser General/Affero General Public License", "free software; you can redistribute it and/or modify", "under the terms of the GNU") and the identifiers of GPL or academic-only tools whose code must never be ported (primer3, oligotm, libprimer3, Sequence Manipulation Suite, SMS2, EMBOSS, pLannotate, CRISPOR). SOURCE_EXEMPT lists four files where a mention is legitimate, each with its reason (CTO ruling and CSO rulings of 6 October 2026):
| File | Reason (summarised) |
|---|---|
content/apps/sequence-toolkit.ts |
excludedSources and oracles name Primer3, SMS2, EMBOSS and CRISPOR as excluded or never run |
content/tools/sequence-toolkit.ts |
The write-up names each method's oracle, Primer3's ntthal among them |
content/apps/sequence-toolkit.docs-entries.ts |
The methods page's definitions (moved verbatim from sequence-toolkit.docs.ts for the methods and checks dialog, D-0085) state the conventions "as Primer3's thal, inferred from its output" |
content/apps/sequence-toolkit/structure.ts |
The hairpin and dimer cards name Primer3 as the oracle that reports a different structure |
Check 5: the registry
Described on Data sources: a sourceMeta per source, a decision or display-only flag for any no-reuse-licence source, an https:// terms page per endpoint, licence pages read within READ_WITHIN_DAYS = 365 of the reference date, and no duplicate hosts.
The listing of GPL and academic-only tools
toolListing() lists every registry oracles entry whose licence matches GPL, academic or non-commercial, and every source with licenceId: "GPL-3.0-or-later-buildtime". It reads only the registry, so the Education pipeline's Blender and Molecular Nodes, which have no registry entry, are not listed.
The allow-list, additions and exceptions
ALLOWED is the board memo's list: MIT, BSD-2-Clause, BSD-3-Clause, Apache-2.0, ISC, 0BSD, CC0-1.0, Unlicense.
ALLOWED_ADDITIONS, each recorded for the General Counsel's sign-off:
| Id | Why it is needed | Held for | Since |
|---|---|---|---|
Zlib |
pako (via 3dmol, directly and through upng-js) is MIT AND Zlib |
General Counsel (D-0010) | 2026-10-05 |
Python-2.0 |
argparse (via molstar's command-line entry, never in the vendored viewer) | General Counsel (D-0010) | 2026-10-05 |
EXCEPTIONS, each with decision: null:
| Package | Licence | Reason (registry wording, summarised) | Server only | Text | Since |
|---|---|---|---|---|---|
caniuse-lite@1.0.30001806 |
CC-BY-4.0 | Browser-support data Next.js requires at build time; data, not code; attribution in the notices file | No | Ships its own licence file | 2026-10-05 |
@img/sharp-libvips-linux-x64@1.3.4 |
LGPL-3.0-or-later | libvips binary for Next's image optimisation; server side only; not redistributed | Yes | textNotRequired: the package ships no licence file |
2026-10-05 |
@img/sharp-libvips-linuxmusl-x64@1.3.4 |
LGPL-3.0-or-later | As above, musl build | Yes | textNotRequired |
2026-10-05 |
@img/sharp-libvips-darwin-arm64@1.3.4 |
LGPL-3.0-or-later | macOS build of the same; not installed on Linux, kept because the lockfile holds it for darwin/arm64 | Yes | textNotRequired |
2026-10-07 |
There is no separate deny-list: a licence the allow-list does not satisfy is refused unless an exception names the package. (An exported DENIED pattern that no check used was removed on 17 October 2026.)
LOCAL_LICENCES (in scripts/lib/licence-texts.mjs, re-exported by scripts/licences.mjs) gives the text for packages whose tarball has none: @nodable/entities and @rdkit/rdkit (files in scripts/licenses/), server-only (scripts/licenses/server-only-LICENSE.txt, MIT, Meta Platforms), and @next/env, @next/swc-linux-x64-gnu, @next/swc-linux-x64-musl, @next/swc-darwin-arm64 and client-only (pointed at node_modules/next/license.md).
The open-questions register (docs/board/open-questions.md, "Held for the General Counsel", 5 October 2026) records the two additions, the caniuse-lite exception and the three @img/sharp-libvips platform binaries (the darwin-arm64 exception of 7 October 2026 among them; the count was corrected from two on 17 October 2026), and that MPL-2.0 (axe-core, lightningcss) and BlueOak (minimatch) development tools are reported, not refused.
The third-party notices file
scripts/notices.mjs runs with npm run vendor (so before dev and build) and writes public/third-party-notices.txt, which is gitignored. Which text travels with what is recorded once, in scripts/lib/licence-texts.mjs, and both this writer and the licence check read it, so the file and the check cannot disagree about a package's text. The file has three parts:
- Packages. The same production closure as check 1 (
walkClosure), inname@versionorder:==== <name>@<version> (<licence>)followed by the package's licence file or itsLOCAL_LICENCEStext (licenceTextPath), or the line "No licence file is included in this package. Its package.json declares: <licence>." On 17 October 2026 the file lists 259 packages, and only the two installed libvips binaries carry that line, as theirtextNotRequiredexceptions allow. (Until that day the writer kept its own two-entry copy ofLOCAL_LICENCES, soserver-only,client-only,@next/env,@next/swc-linux-x64-gnuand@next/swc-linux-x64-muslwent out with the line although check 1 counted them as having a text.) - Third-party code bundled inside the vendored builds (
BUNDLED_NOTICES): InChI 1.07.3, compiled intoRDKit_minimal.wasm, with the text inscripts/licenses/inchi-LICENSE.txt(see Vendored browser builds). - Fonts (
FONT_LICENCES): the four familiessrc/lib/fonts.tsself-hosts, each with its SIL Open Font License 1.1 text (see Fonts).
scripts/licences.test.mjs checks the output: every package check 1 counts as having a text is written with it, the five packages above carry their MIT text, the InChI text names its three copyright holders and the vendored RDKit build carries it, and the font list equals the families src/lib/fonts.ts imports from next/font/google, so a new family without a recorded licence fails npm test. The registry links the file as "Third-party notices" (/third-party-notices.txt) beside RDKit, OpenChemLib, uqr and Assay's RDKit source; the InChI source entry in content/tools/molecule-workbench.ts has no such link.
The notices file does not include the licences of any third-party code the vendored builds bundle beyond InChI and what each npm package ships; no script checks the minimal RDKit build, the Mol* viewer or 3Dmol.js for other bundled code with its own notice requirement.
Build-time tools: Python, R and Blender
None of these is a dependency of the app. Each pipeline folder pins its Python packages in a requirements.txt and its README says to install into a virtual environment outside the tracked tree (Data pipeline). Licences are as recorded in the requirement comments, the registry oracles and sources, or the folder's README; "not recorded" means the repository does not state one.
| Pipeline | Requirements | Licences as recorded | Python | Role |
|---|---|---|---|---|
assay-analyser/requirements.txt |
numpy==2.4.6 |
BSD-3-Clause | Not stated | Seeded generator of synthetic curves and the MTT plate |
assay-analyser/requirements-irls.txt |
scipy==1.17.0, numpy==2.3.5 |
BSD-3-Clause (registry for SciPy and NumPy) | 3.12.14 | Relative-weighting IRLS oracle |
assay-analyser/reference.R |
R 4.3.3, drc 4.0-0, MASS 7.3-60.0.1, jsonlite 1.8.8; drc's dependencies car 3.1-2, gtools 3.9.5, multcomp 1.4-25, plotrix 3.8-4, sandwich 3.1-0, scales 1.3.0 (Ubuntu packages) | R: GPL-2 or GPL-3; drc: GPL-2; MASS: GPL-2 or GPL-3; jsonlite: MIT; drc's dependencies: "GPL or MIT". reference.R itself is MIT and calls drc by its public API |
n/a | Curve-fitting oracle |
bioreactor-simulator/requirements.txt |
scipy==1.17.0, numpy==2.3.5 |
BSD-3-Clause | 3.12.14 (PSF-2.0, registry) | ODE oracle (solve_ivp Radau) |
drug-pipeline-explorer/precedent/requirements.txt |
openpyxl==3.1.5, pypdf==6.19.0 |
Not recorded | 3.12 in the snapshot workflow | FDA precedent snapshots and fixtures |
drug-pipeline-explorer/verify_stems.py (CI) |
pypdf, unpinned |
Not recorded | 3.12 | Weekly stem check |
education/requirements.txt |
bpy==5.2.2, molecularnodes==520.2.0, nodebpy==520.27.0, biotite==1.7.1, numpy==2.5.3, scipy==1.18.1, imageio-ffmpeg==0.6.0, Pillow==12.3.0 |
bpy GPL-3.0-or-later and Molecular Nodes GPL-3.0-or-later (Cell's registry and README); Biotite, NumPy, SciPy BSD-3-Clause; nodebpy, imageio-ffmpeg and Pillow not recorded | 3.13 | Education posters, videos and scenes |
inside-a-cell/requirements.txt |
numpy==2.5.3, scipy==1.18.1, biotite==1.7.1, bpy==5.2.2, molecularnodes==520.2.0 |
Blender binaries GPL-3.0-or-later (source GPL-2.0-or-later); Molecular Nodes GPL-3.0-or-later; others BSD-3-Clause | 3.13 | Trimmed structures and stills |
lab-calculators/requirements.txt |
rdkit==2026.3.6, numpy==2.4.6, biopython==1.85 |
BSD-3-Clause; Biopython Licence Agreement (BSD-3-Clause file by file) | 3.11 | Calc oracles |
molecule-workbench (README, no requirements file) |
rdkit==2026.3.6 |
BSD-3-Clause | Not stated | PAINS data, QED notice, reference fixtures, library comparison; since Wave 4 the fingerprint-policy and series oracles and pipeline/walks/nearest/walk_values.py |
protein-explorer (no requirements file) |
Biopython 1.88 for align_reference.py and blosum62.py (version recorded, not enforced); standard library for the AlphaMissense and substitution oracles |
Biopython Licence Agreement or BSD-3-Clause (as recorded elsewhere) | Not stated | Wave 4 aligner and AlphaMissense oracles |
plasmid-map/requirements.txt |
biopython==1.88 |
Biopython Licence Agreement or BSD-3-Clause | 3.11 | Plasmid oracles |
sequence-toolkit/requirements.txt |
biopython==1.88, primer3-py==2.3.1 (bundles libprimer3 2.6.1), rdkit==2026.03.6 (for peptides.py) |
Biopython as above; primer3-py GPL-2.0-or-later; RDKit BSD-3-Clause | 3.11.15 | Sequence oracles; reference.py is MIT |
oracle-env/Dockerfile (the oracle image) |
R 4.4.3 (rocker/r-ver:4.4.3) on the CRAN snapshot of 2026-09-30 with drc, car, chemCal, investr, outliers, multcomp, mvtnorm, jsonlite, MASS and survival; CPython 3.11.15 with five environments from the Assay, Sequence and Calc requirements files above (openpyxl 3.1.5 in the three Assay ones); MAFFT 7.526 (core only, built from source); EMBOSS 6.6.0 (Ubuntu package). Resolved versions in pipeline/oracle-env/R-packages.csv and python-packages.txt |
R and the R packages GPL (jsonlite MIT); MAFFT core BSD (its license file, read 12 October 2026; extensions not built); EMBOSS GPL; Python packages as above |
3.11.15 | Runs the Assay oracles (and is ready for Sequence and Calc) offline in Actions; never shipped (Rule G) |
EMBOSS needle 6.6.0.0 (GPL) was run once, locally, for the protein aligner's cross-check (docs/science/evidence/protein-align-2026-10-11/). EMBOSS 6.6.0 is now also in the oracle image, for cai among others, as an offline oracle only. It is not in any registry oracles entry, so toolListing() does not list it, and the licence scan keeps its name out of src/ and content/.
Other offline tools named in the registry oracles: NCBI ORFfinder 0.4.3 (public domain, NCBI) and the Expasy ProtParam web form (SIB terms, "To be checked") for Sequence; Python fractions and decimal (Python-2.0 or PSF-2.0) for Calc, Sequence and Plasmid.
The pipeline notes record these rules for GPL tools: they run offline, their numbers are committed as fixtures with the tool, version and licence, and their code and parameter files are never copied into src/. pipeline/sequence-toolkit/README.md records that primer3_config files are never copied; pipeline/inside-a-cell/README.md and pipeline/education/README.md state that the GPL does not cover the rendered images and videos. The open-questions register holds the related items (Sequence naming GPL tools, Primer3 conventions, retention of R and drc output in evidence logs) for the General Counsel.
The scheduled and snapshot workflows install Python 3.12 (actions/setup-python@v5) whatever version a README names.
Fonts and other assets
Fonts
src/lib/fonts.ts loads four families through next/font/google:
| Family | Variable | Options | Licence |
|---|---|---|---|
| Inter | --font-inter |
subsets: ["latin"], display: "swap" |
OFL-1.1 |
| Bricolage Grotesque | --font-bricolage |
subsets: ["latin"], display: "swap" |
OFL-1.1 |
| IBM Plex Mono | --font-plex-mono |
weights 400, 500, 600; subsets: ["latin"], display: "swap" |
OFL-1.1 |
| Source Serif 4 | --font-source-serif |
weights 400, 500, 600; subsets: ["latin", "latin-ext", "greek"] (Greek for subject names such as α-synuclein), display: "swap"; the workspace subject face and headline-answer face since D-0082 (13 October 2026) |
OFL-1.1 |
Next downloads the CSS and font files at build time and serves them from the site; its documentation states that the browser sends no requests to Google. The build therefore needs network access to Google Fonts. The CSP's font-src 'self' allows only these self-hosted files.
All four families are under the SIL Open Font License 1.1 (OFL-1.1). The licence of each, its text and where the text was read are recorded in FONT_LICENCES in scripts/lib/licence-texts.mjs, and the four texts are written into public/third-party-notices.txt (its "Fonts" part). Each text is the family's licence file copied byte for byte from the font's own repository on 17 October 2026:
| Family | Text in the repository | Copied from | Copyright line in that file |
|---|---|---|---|
| Inter | scripts/licenses/inter-OFL.txt |
https://github.com/rsms/inter/blob/master/LICENSE.txt | "Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)" |
| Bricolage Grotesque | scripts/licenses/bricolage-grotesque-OFL.txt |
https://github.com/ateliertriay/bricolage/blob/main/OFL.txt | "Copyright 2022 The Bricolage Grotesque Project Authors (https://github.com/ateliertriay/bricolage)" |
| IBM Plex Mono | scripts/licenses/ibm-plex-mono-OFL.txt |
https://github.com/IBM/plex/blob/master/LICENSE.txt | "Copyright © 2017 IBM Corp. with Reserved Font Name "Plex"" |
| Source Serif 4 | scripts/licenses/source-serif-4-OFL.txt |
https://github.com/adobe-fonts/source-serif/blob/release/LICENSE.md | "Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. …" |
The licence body of each file matches SIL's text (https://openfontlicense.org/documents/OFL.txt, read the same day) word for word, except that Inter's upstream copy heads one section "PERMISSION AND CONDITIONS" where SIL's reads "PERMISSION & CONDITIONS". The files next/font serves are Google Fonts' builds; Google's own OFL.txt for each family (github.com/google/fonts, ofl/<family>/OFL.txt, read the same day for comparison) has the same body, and names the copyright as "2020 The Inter Project Authors" for Inter and "2014 The Source Serif 4 Project Authors" for Source Serif 4 (the other two match upstream). scripts/licences.test.mjs fails if src/lib/fonts.ts imports a family that FONT_LICENCES does not list.
The design documents record the same licence: docs/design/prd-inside-a-cell.md (the asset table, with the intended credit line "Fonts: Inter, Bricolage Grotesque, IBM Plex Mono (SIL Open Font License 1.1).") and docs/design/build-spec-inside-a-cell.md, and the CPO memo of 13 October 2026 for Source Serif 4. That credit line is not in any content file and does not name Source Serif 4; OFL-1.1 exists as a LicenceId, but no registry source or export uses it.
Share images and the per-app icon are drawn with next/og ImageResponse (src/components/suite/marketing/og-card.marketing.tsx, src/app/(workspace)/[app]/icon.tsx) using fontFamily: "sans-serif", so they render with the font next/og supplies by default; its licence is not recorded in the repository.
Images, media and other files
| Asset | Origin | Licence as recorded |
|---|---|---|
src/app/favicon.ico, src/app/icon.svg |
The suite mark; last changed in commit 42e2437 ("Adopt the Bench mark across Drybench and Workspace") | Not recorded; no third-party source named |
public/data/inside-a-cell/stills/*.webp |
Rendered by pipeline/inside-a-cell/render.py with Blender and Molecular Nodes from CC0 PDB coordinates |
Coordinates CC0; tools GPL, stated as not covering the outputs |
public/data/education/*-structure.webp, *-guide.mp4, *-guide.webm, structures/ |
Rendered by pipeline/education/molecular.py; FFmpeg crossfades and encodes (through imageio-ffmpeg) |
Coordinates CC0; FFmpeg's licence not recorded |
public/media/landing/study-light.jpg, study-dark.jpg |
Added in commit e7f8080 ("Redesign landing around connected dry-lab workspace") | Not recorded; no file in src/ or content/ references them |
public/tools/molecule-workbench/qed-notice.txt |
Written by rdkit_reference.py pains |
Novartis BSD-3-Clause notice; its first line names the page as /molecule/app (the old /apps/molecule-workbench/app until 17 October 2026) |
public/verification/<slug>/<version>/ |
Published oracle fixtures | MIT where the registry records them (Assay, Plasmid, Bioreactor fixtures) |
Product page posters (posterUrl in content/apps/routes.ts) |
/media/<slug>/preview.webp; no such files exist under public/media/, and the posters are drawn from the app mark until a file exists (AppEntry.preview comment) |
n/a |
Data files and their licences are listed on Data sources.
What would need attention before commercial shipping
These are the facts the code and register record. Whether any licence permits sale is held for the General Counsel (D-0010) and checked at the pre-live pass (D-0014).
- No GPL code ships. The production closure passes the allow-list with three recorded exceptions; the vendored builds are MIT and BSD-3-Clause; the source scan finds no GPL header or ported GPL tool. GPL tools (primer3-py, R, drc, MASS, Blender, Molecular Nodes) are build-time only. On the current record, no dependency needs a rewrite.
- LGPL libvips binaries. The three
@img/sharp-libvips-*exceptions rest on "server side only, never bundled for the browser". The check that enforces this needs.next/staticand so does not run in CI, where the licence check runs before the build. If the exceptions were refused, the code that depends on them is Next's image optimisation behindnext/image(Cell stills, marketing posters and the landing Education band). Whether to disable optimisation or change approach would be an engineering decision. - CC-BY-4.0 data in the toolchain.
caniuse-liteis excepted as build-time data with attribution in the notices file. - Permissive additions.
ZlibandPython-2.0are allowed pending sign-off. - Notices. Since 17 October 2026 the notices file carries every package text the check counts, InChI's licence and the OFL text of the four self-hosted fonts. What remains is attribution, not code: the fonts' credit line is not in any content file, and no script checks the vendored builds for other bundled code with its own notice requirement.
- Share-alike data. ChEMBL-derived data (the Molecule library and the public search catalogue) is a data-licence question (Q-03, Q-26), not a dependency question; see Data sources.
Gaps and divergences found
| Finding | Location |
|---|---|
The copyleft browser-bundle assertion (inBrowserBundle) runs only when .next/static exists; CI runs the licence check before the build, so it never runs there, and locally it reads whatever build is present |
scripts/licences.mjs (inBrowserBundle, checkProduction); .github/workflows/ci.yml (check job) |
The fonts' credit line in docs/design/prd-inside-a-cell.md ("Fonts: Inter, Bricolage Grotesque, IBM Plex Mono (SIL Open Font License 1.1).") is not in any content file and does not name Source Serif 4; the licence texts themselves are in the notices file |
docs/design/prd-inside-a-cell.md:117,308; scripts/lib/licence-texts.mjs (FONT_LICENCES) |
| The InChI source entry in the Molecule source list links no "Third-party notices", although its text is in the notices file | content/tools/molecule-workbench.ts (source "InChI (bundled in RDKit.js)") |
@img/sharp-wasm32 (Apache-2.0 AND LGPL-3.0-or-later AND MIT) is installed as extraneous; on FreeBSD or WebContainers, where it would be reachable, no exception covers it |
package-lock.json; scripts/licences.mjs EXCEPTIONS |
toolListing() and check 5 read only the registry, so the Education pipeline's GPL build tools are not listed |
scripts/licences.mjs (toolListing); pipeline/education/requirements.txt |
Engine versions are typed in registry source names and data files with no test tying them to package.json |
See Version pinning policy |
@types/node is ^20 while the engine floor is Node 22.18 |
package.json |
The weekly stems job installs pypdf unpinned |
.github/workflows/scheduled.yml |
The licences of openpyxl, pypdf, nodebpy, imageio-ffmpeg (and the FFmpeg binary it supplies) and Pillow are not recorded |
The pipeline requirements.txt files |
Closed on 17 October 2026 (the enterprise review's housekeeping track, F1): the notices writer's two-entry copy of LOCAL_LICENCES (now one shared record, scripts/lib/licence-texts.mjs), the unused DENIED export (removed), InChI's missing licence text (now beside the vendored build and in the notices file), the fonts' missing OFL text (now in the notices file; DAT-09 in Known issues), the register's count of two libvips exceptions (now three) and qed-notice.txt's old Molecule address (now /molecule/app, in the file and in rdkit_reference.py, which writes it).
Adding or upgrading a dependency
- Prefer a package under a licence in
ALLOWED. A GPL dependency, or a feature built on one, means a rewrite at the pre-live pass, so say so when proposing it. - For a heavy engine, load it on demand and serve it with its licence text: add it to
packagesinscripts/vendor.mjswith an exact pin and tovendorVersionsinsrc/lib/vendor.ts, and declare any CSP allowance it needs in the app'sdataPolicy.cspAllowanceswith the reason. - If its tarball has no licence file, add the text under
scripts/licenses/and an entry inLOCAL_LICENCESinscripts/lib/licence-texts.mjs, which both the check and the notices writer read. Third-party code compiled inside a vendored build goes inBUNDLED_NOTICESthere, and a new web font inFONT_LICENCES. - A licence outside the allow-list needs an
EXCEPTIONSentry keyed byname@versionwithlicence,reason,heldForandsince, and an entry in the open-questions register's held list. - Update the version wherever it is typed in text (see Version pinning policy), and the registry source if the app lists the library as a source.
- Run
npm run check-licences,npm testandnpm run build, then look at the generatedpublic/third-party-notices.txt.