You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Docker image dependency tree is resolved fresh at build time, not from the published shrinkwrap #1960
SummaryThe Dockerfile installs harper from a locally built tarball:```
npm install --ignore-scripts --global harper-.tgz npm decides whether to honour a package's bundled `npm-shrinkwrap.json` from the `_hasShrinkwrap` flag in the **registry packument** — metadata the registry sets at publish time. A local tarball has no packument, so npm never learns the shrinkwrap exists: it opens the tarball, reads `package.json`, and resolves the whole tree fresh.## EvidenceThe *same* published `harper@5.1.23` artifact, installed two ways:| | shrinkwrap pin | via registry | via local tarball | latest on npm | |---|---|---|---|---| | fastify | 5.8.5 | 5.8.5 | **5.10.0** | 5.10.0 | | chokidar | 4.0.3 | 4.0.3 | 4.0.3 | 5.0.0 | | graphql | 16.14.2 | 16.14.2 | 16.14.2 | 17.0.2 |fastify is the discriminator — the tarball install resolved to latest rather than the pin. (chokidar and graphql match only coincidentally: harper's `^4.0.3` / `^16.10.0` ranges cap below those new majors.) The registry install produced exactly 794 packages, matching the shrinkwrap's 794 entries, in an isolated nested tree.## Why it matters1. **The image is not reproducible.** Two builds of the same harper commit, weeks apart, can ship different dependency trees — whatever is newest on npm within our semver ranges at build time. 2. **The image does not match what npm consumers get.** Registry consumers install the pinned tree; the image installs something else. 3. It is why the image still carries the react-native tree after #1937's shrinkwrap prune (see #1959) — that fix reaches registry installs but not this one.## DirectionMake the image install honour the shrinkwrap. Extracting the tarball and installing in place works — the shrinkwrap is then present as the lockfile:
tar -xzf harper-.tgz --strip-components=1 -C
&& cd && npm install --omit=dev --ignore-scripts
```Measured locally (macOS, like-for-like): 444M -> 268M with #1959's prune in place, and the tree becomes pinned. npm ci would be exact rather than merely shrinkwrap-guided, but currently trips the sync check because the published `package.json` retains `devDependencies` while the shipped shrinkwrap has them pruned.Open questions for whoever picks this up:
Extract-and-install vs. keeping npm install --global and accepting an unpinned image.
Whether to make npm ci viable (strip devDependencies from the packed package.json), which would give an exactly-pinned image.
Checked whether this has actually bitten a published image, since #2043 raised the possibility that the unpinned resolve picked up @harperfast/rocksdb-js 2.6.x. Short version: the mechanism is confirmed live on the shipped 5.2.0 artifact, but no published image was broken by it.
The mechanism reproduces on the released tarball. Installing harper@5.2.0 the way the Dockerfile does — from a local .tgz, so npm never sees a packument and never learns the bundled shrinkwrap exists:
bundled npm-shrinkwrap.json pins: @harperfast/rocksdb-js 2.5.0
fresh resolve from the tarball: @harperfast/rocksdb-js 2.7.0
Both v5.2.0 Dockerfiles still use that path (npm install --ignore-scripts --global harper-*.tgz in harper, npm install --global harperfast-harper-pro-*.tgz in harper-pro), so every image build resolves ^2.5.0 to whatever is latest at build time. The relevant publish dates: 2.6.0 and 2.6.1 on 2026-07-31, 2.7.0 on 2026-08-04 — all inside the ^2.5.0 range, all after the shrinkwrap was written.
But the 5.2.0 image is fine. The Release Harper Pro to Environments run of 2026-08-01T02:22 (immediately after the 5.2.0 tag) is green end to end, including the stages that would have caught a broken table open:
Build Docker image (v5.2.0) — success
Deploy to stage hosts — success
Health check stage — success
Smoke test — create/verify cluster (v5.2.0) — success
A cluster was created and verified against that image, so whatever rocksdb-js it resolved at build time opens tables correctly. Nothing needs rebuilding, and the fleet isn't exposed today.
What that leaves. The exposure isn't a broken image, it's that the image's dependency tree is decided by publish timing rather than by anything we tested. Two consequences worth separating:
Every rebuild of the same tag can produce a different tree. harper:5.2.0 built today resolves 2.7.0; built on 2026-08-01 it resolved something else. That's a reproducibility hole in a released artifact, independent of whether any particular resolve is broken.
The next incompatible publish inside a caret range lands in the image with no Harper change to review. This time the stage smoke test would have caught a total failure — it wouldn't necessarily catch a subtler incompatibility, and it runs after the image is already built and tagged.
Keeping this at P1 on that basis rather than escalating: real and structural, but not currently breaking anything. #2042 remains the fix.
Activity
docs(design): record how the published shrinkwrap governs installs
docs(design): record how the published shrinkwrap governs installs
kriszyp commentedon Aug 6, 2026
Checked whether this has actually bitten a published image, since #2043 raised the possibility that the unpinned resolve picked up
@harperfast/rocksdb-js2.6.x. Short version: the mechanism is confirmed live on the shipped 5.2.0 artifact, but no published image was broken by it.The mechanism reproduces on the released tarball. Installing
harper@5.2.0the way the Dockerfile does — from a local.tgz, so npm never sees a packument and never learns the bundled shrinkwrap exists:Both v5.2.0 Dockerfiles still use that path (
npm install --ignore-scripts --global harper-*.tgzin harper,npm install --global harperfast-harper-pro-*.tgzin harper-pro), so every image build resolves^2.5.0to whatever is latest at build time. The relevant publish dates: 2.6.0 and 2.6.1 on 2026-07-31, 2.7.0 on 2026-08-04 — all inside the^2.5.0range, all after the shrinkwrap was written.But the 5.2.0 image is fine. The
Release Harper Pro to Environmentsrun of 2026-08-01T02:22 (immediately after the 5.2.0 tag) is green end to end, including the stages that would have caught a broken table open:A cluster was created and verified against that image, so whatever rocksdb-js it resolved at build time opens tables correctly. Nothing needs rebuilding, and the fleet isn't exposed today.
What that leaves. The exposure isn't a broken image, it's that the image's dependency tree is decided by publish timing rather than by anything we tested. Two consequences worth separating:
harper:5.2.0built today resolves 2.7.0; built on 2026-08-01 it resolved something else. That's a reproducibility hole in a released artifact, independent of whether any particular resolve is broken.Keeping this at P1 on that basis rather than escalating: real and structural, but not currently breaking anything. #2042 remains the fix.
— KrAIs (Claude Opus 5)
fix(docker): install harper from the packed tarball's own shrinkwrap