Context
#298 dropped --frozen-lockfile from packages/opencode/build.sh to unblock a rebuild: minimal's shipped bun (1.3.x) resolves opencode's upstream-committed lockfile differently and rejected it (lockfile had changes, but lockfile is frozen). That was the right call to unblock, but it trades dependency-version reproducibility — bun now floats the lockfile, so two builds of the same opencode version can resolve different transitive deps. (The install already network-fetches deps, so the build isn't hermetic either way.)
Proper fix
Restore deterministic resolution by vendoring a bun.lock regenerated with minimal's bun, and reinstating --frozen-lockfile against it:
- With minimal's shipped bun, run
bun install on the pinned opencode version to generate a matching bun.lock.
- Vendor it in
packages/opencode/ (or have build.sh overwrite the upstream tarball's lockfile with it before the frozen install).
- Re-add
--frozen-lockfile so a future build fails loudly if resolution drifts, instead of silently floating.
- Refresh the vendored lockfile whenever opencode's version or the shipped bun is bumped — a step the auto-updater should own (relates to the generated-
.ncl validation theme in gominimal/pkgmgr-rs#389).
Why it matters
Floating deps is a supply-chain surface (an upstream transitive dep can change under us between builds) and makes opencode's artifact non-reproducible — exactly the property the signed-index / provenance work (build-servers#86, inbox#37) wants to be able to assert.
Related (separate)
The same build-time-network fragility bit cabal in the same #298 rebuild — its bootstrap live-fetches from http://hackage.haskell.org with a 10s timeout and timed out (transient). Vendoring those bootstrap tarballs (alex/happy/…) into the source mirror is the analogous fix; worth its own issue if it recurs.
Context
#298 dropped
--frozen-lockfilefrompackages/opencode/build.shto unblock a rebuild: minimal's shipped bun (1.3.x) resolves opencode's upstream-committed lockfile differently and rejected it (lockfile had changes, but lockfile is frozen). That was the right call to unblock, but it trades dependency-version reproducibility — bun now floats the lockfile, so two builds of the same opencode version can resolve different transitive deps. (The install already network-fetches deps, so the build isn't hermetic either way.)Proper fix
Restore deterministic resolution by vendoring a
bun.lockregenerated with minimal's bun, and reinstating--frozen-lockfileagainst it:bun installon the pinned opencode version to generate a matchingbun.lock.packages/opencode/(or havebuild.shoverwrite the upstream tarball's lockfile with it before the frozen install).--frozen-lockfileso a future build fails loudly if resolution drifts, instead of silently floating..nclvalidation theme in gominimal/pkgmgr-rs#389).Why it matters
Floating deps is a supply-chain surface (an upstream transitive dep can change under us between builds) and makes opencode's artifact non-reproducible — exactly the property the signed-index / provenance work (build-servers#86, inbox#37) wants to be able to assert.
Related (separate)
The same build-time-network fragility bit cabal in the same #298 rebuild — its bootstrap live-fetches from
http://hackage.haskell.orgwith a 10s timeout and timed out (transient). Vendoring those bootstrap tarballs (alex/happy/…) into the source mirror is the analogous fix; worth its own issue if it recurs.