Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions config/defaults/tool_versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,29 @@ tools:
version: "1.33"
source: pypi

# Babraham publish no release API, so the URL is constructed from the version
# and cannot be discovered. Bump both together.
# Babraham publish no release API, and no GitHub release assets either -- all six
# of their GitHub releases carry none -- so upstream the URL is constructed from
# the version and cannot be discovered. Because of that, and only because of that,
# the archive is VENDORED: see docs/compliance/vendored-archives.md.
#
# MEASURED 2026-09-22: CI went red on a commit that touched nothing near FastQC
# because www.bioinformatics.babraham.ac.uk served an expired TLS certificate.
# With no upstream release asset to fall back on, the pin could only point at that
# one host, so a third party's certificate renewal was able to stop our builds.
#
# The vendored asset is the SAME BYTE-FOR-BYTE ARTEFACT: the sha256 below is
# unchanged from the upstream pin, and it was established while upstream was
# healthy. Integrity comes from that checksum -- the retrieval itself used
# `curl --insecure` (recorded in the release notes) because upstream's certificate
# was already invalid when the file was captured. Nothing changed but who serves it.
#
# Bump the version, the URL and the checksum together.
fastqc:
version: "0.12.1"
source: archive
archives:
any:
url: "https://www.bioinformatics.babraham.ac.uk/projects/fastqc/fastqc_v0.12.1.zip"
url: "https://github.com/hyperpolymath/MetaManifold-WebUI/releases/download/vendored/fastqc-v0.12.1/fastqc_v0.12.1.zip"
sha256: "5f4dba8780231a25a6b8e11ab2c238601920c9704caa5458d9de559575d58aa7"

# No precompiled cd-hit binary is published for Linux, so the installer prefers
Expand Down
61 changes: 61 additions & 0 deletions docs/compliance/vendored-archives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!--
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# Vendored archives

Third-party build inputs that are served from **this repository's own releases** instead
of from the party that publishes them. Vendoring is a decision, not a convenience: every
entry here states why the upstream location cannot be relied on, and every archive is
byte-identical to the upstream release it came from.

## The rule

1. **The checksum is the integrity claim, never the transport.** A vendored archive is
accepted only against the SHA-256 that was already pinned while upstream was healthy.
If a capture had to be made over a broken connection, that is recorded below rather
than glossed.
2. **Never re-checksum to make a download succeed.** If the bytes differ, the vendoring
failed — investigate, do not "fix" the pin.
3. **Licence travels with the archive.** The upstream licence stays inside the archive,
unmodified, and is named below.
4. **Repointing back at a third party is a decision.** `test/unit/test_install_pins.jl`
fails by name if a vendored URL quietly returns to its original host.

## Entries

### `fastqc_v0.12.1.zip` — FastQC 0.12.1

| | |
| --- | --- |
| Release | [`vendored/fastqc-v0.12.1`](https://github.com/hyperpolymath/MetaManifold-WebUI/releases/tag/vendored%2Ffastqc-v0.12.1) (marked *pre-release* — it is a build input, not a version of this software) |
| Upstream | `https://www.bioinformatics.babraham.ac.uk/projects/fastqc/fastqc_v0.12.1.zip` |
| SHA-256 | `5f4dba8780231a25a6b8e11ab2c238601920c9704caa5458d9de559575d58aa7` |
| Licence | GNU GPL v3 (the archive carries `FastQC/LICENSE.txt`), redistributed unmodified |
| Captured | 2026-09-22 |
| Pinned in | `config/defaults/tool_versions.yml` (`tools.fastqc.archives.any`) |

**Why.** On 2026-09-22 CI went red on a commit that touched nothing near FastQC: the
upstream host served an **expired TLS certificate**. There was no way out through the pin
file, because FastQC publishes **no GitHub release assets** — all six of its GitHub
releases carry none — so the URL could only ever point at that single host. A third
party's certificate renewal could therefore stop our builds, and did.

**Provenance.** The archive was captured once from the upstream URL above. The capture
used `curl --insecure`, because upstream's certificate was already invalid at that
moment; this is stated plainly because it is the one detail a reader should not have to
infer. Integrity does not rest on that transfer: the SHA-256 above is **unchanged from
the original upstream pin**, which was established while upstream was healthy, and the
captured file verifies against it. These are the bytes CI has always installed; only the
serving host changed.

**Effect.** CI installs FastQC from this repository's releases, over a connection to
GitHub — the same host that already serves `vsearch` and `swarm` — so the FastQC host is
no longer on the critical path for building or reproducing the pipeline.

## Adding an entry

Capture the archive, verify it against the existing pinned checksum (or, for a new tool,
establish a checksum through a healthy source and record how), attach it to a release
tagged `vendored/<tool>-v<version>` and marked as a pre-release, repoint the URL in
`config/defaults/tool_versions.yml` keeping the checksum unchanged, add an entry here
with the same fields, and extend the guard in `test/unit/test_install_pins.jl`.
27 changes: 27 additions & 0 deletions test/unit/test_install_pins.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,33 @@ end
end
end

@testset "the FastQC archive is vendored, and stays vendored" begin
# Guarded as a decision rather than described as a fact, because the failure
# mode is silent: a URL that quietly points back at a third party still
# downloads, still verifies against the checksum, and gives no sign that CI is
# once again dependent on someone else's certificate renewal.
#
# MEASURED 2026-09-22: CI went red on a commit that touched nothing near FastQC
# because www.bioinformatics.babraham.ac.uk served an expired TLS certificate.
# FastQC publishes no release assets upstream -- all six of its GitHub releases
# carry none -- so the pin had nowhere else to point. The archive is now served
# from this repository's own releases (see docs/compliance/vendored-archives.md):
# the same bytes, kept against the checksum that was already pinned, so only the
# serving host changed.
#
# Repointing this at a third-party host again is a decision somebody should make
# deliberately, so it fails here by name instead of drifting back in silence.
fastqc_url = pins["tools"]["fastqc"]["archives"]["any"]["url"]
@test startswith(fastqc_url,
"https://github.com/hyperpolymath/MetaManifold-WebUI/releases/download/")
@test !occursin("babraham.ac.uk", fastqc_url)

# The vendored copy is only defensible while it is provably the upstream
# artefact. This is that checksum, unchanged from the original upstream pin.
@test pins["tools"]["fastqc"]["archives"]["any"]["sha256"] ==
"5f4dba8780231a25a6b8e11ab2c238601920c9704caa5458d9de559575d58aa7"
end

@testset "install.jl holds no versions of its own" begin
src = read(INSTALL_JL, String)

Expand Down
Loading