Split out of the Pinned-Dependencies work in chore/pin-container-digests, which pinned the five container base images by digest and added Dependabot to refresh them. The remaining warnings in the same Scorecard check are all package-manager invocations inside the Dockerfiles, and they need a different mechanism.
Scorecard (2026-07-27, score 7.2, Pinned-Dependencies 3/10) reports these after the digest pins land:
Warn: pipCommand not pinned by hash: .devcontainer/Dockerfile:51-55 (x3)
Warn: pipCommand not pinned by hash: Dockerfile:46-48 (x3)
Warn: pipCommand not pinned by hash: docker/Dockerfile:34
Warn: npmCommand not pinned by hash: docker/Dockerfile:31
Warn: downloadThenRun not pinned by hash: docker/Dockerfile:24-28
Why this is not a one-liner
pip install --require-hashes is all-or-nothing: once any hash is supplied, every install requirement including transitive ones must carry a hash. That means generating a fully hashed constraints file, and this repo's installs are awkward for it:
Dockerfile:46-48 installs torch from https://download.pytorch.org/whl/cpu, a second index, then .[postgresql] from the local tree.
.devcontainer/Dockerfile:51-55 installs exact versions already (torch==2.11.0, sentence-transformers==5.4.1, flashrank==0.2.10) but exact versions are not hashes and do not satisfy the check.
docker/Dockerfile:24-28 is the NodeSource setup_22.x script piped into bash, which is the downloadThenRun finding. Pinning it means vendoring the key and apt source rather than hashing the script.
docker/Dockerfile:31 is npm install -g @anthropic-ai/claude-code, deliberately unversioned so the image tracks the current CLI.
There is a real trade-off in each case, and uv.lock already exists as a source of truth that a hashed constraints file could be generated from.
Acceptance criteria
Note
The .devcontainer and docker/ images have no CI build at all, so a regression in either is currently invisible. That gap is worth its own issue if this one does not close it.
Split out of the Pinned-Dependencies work in
chore/pin-container-digests, which pinned the five container base images by digest and added Dependabot to refresh them. The remaining warnings in the same Scorecard check are all package-manager invocations inside the Dockerfiles, and they need a different mechanism.Scorecard (2026-07-27, score 7.2, Pinned-Dependencies 3/10) reports these after the digest pins land:
Why this is not a one-liner
pip install --require-hashesis all-or-nothing: once any hash is supplied, every install requirement including transitive ones must carry a hash. That means generating a fully hashed constraints file, and this repo's installs are awkward for it:Dockerfile:46-48installstorchfromhttps://download.pytorch.org/whl/cpu, a second index, then.[postgresql]from the local tree..devcontainer/Dockerfile:51-55installs exact versions already (torch==2.11.0,sentence-transformers==5.4.1,flashrank==0.2.10) but exact versions are not hashes and do not satisfy the check.docker/Dockerfile:24-28is the NodeSourcesetup_22.xscript piped intobash, which is thedownloadThenRunfinding. Pinning it means vendoring the key and apt source rather than hashing the script.docker/Dockerfile:31isnpm install -g @anthropic-ai/claude-code, deliberately unversioned so the image tracks the current CLI.There is a real trade-off in each case, and
uv.lockalready exists as a source of truth that a hashed constraints file could be generated from.Acceptance criteria
pipCommand,npmCommandanddownloadThenRunwarning above is either resolved, or documented in-file with the reason it is deliberately unpinned and what compensates for it.uv.lockby a committed script, not hand-maintained.Dockerfilestill passes the blocking Docker Smoke job inci.yml(the bare-container DB-less contract).docker/Dockerfileand.devcontainer/Dockerfileare built at least once as evidence, since no CI job builds either today.Note
The
.devcontaineranddocker/images have no CI build at all, so a regression in either is currently invisible. That gap is worth its own issue if this one does not close it.