An audit of the six code repositories found eleven open issues fixed on main with commits and beds to show (025, 027, 033, 036, 037, 040, 045, 047, 050, 052, 053), three partly (007, 026, 035), nine not (020, 031, 041, 046, 049, 054, 064, 065, 066) and one whose fix would live outside those repos (006). Resolved ones name their evidence; partly ones say what remains; 041 records that the exposure has widened since it was reported.
3.9 KiB
status: resolved opened: 2026-09-15 located-in: [] fixed-by: mesh-tools b618057 (the SDK resolved by version from the registry, one pin); mesh-host 7986306; mesh-controller 4b9bc50. Caveat: the base image still builds with npm install and no lock, so the build is not reproducible amended-design:
053 — The SDK is pinned twice, and the two disagree
Symptom
The module that carries the tool runtime names the SDK two ways, and they are not the same thing:
package.json @novox/mesh-sdk -> git+https://<the forge>/mesh-sdk.git#<a commit>
package-lock.json @novox/mesh-sdk -> ../mesh-sdk
The manifest names a commit in a repository any machine can reach. The lock names a sibling directory, which exists on the workstation the lock was generated on and nowhere else.
It builds anyway, because the recipe runs npm install — which tolerates a lock that disagrees
with its manifest and re-resolves from the manifest. It is the one command that hides this.
Why this matters
A lock file exists to make a build reproducible, and this one describes one machine. npm ci —
the command for exactly the case a lock is for — fails here, or worse, succeeds against whatever
happens to be at that path.
It is the first thing a fresh mesh builds. The toolchain image carries the SDK, and everything with code of its own is compiled inside it. A dependency resolved differently on the build machine than on a workstation is a difference in every module the mesh will ever build, arriving as a compile error or a runtime mismatch far from here.
And it is about to be copied. Each language's toolchain will carry that language's SDK the same way (ADR 0074). Whatever this repository does, the Rust and Python ones will do, so the shape is worth getting right before there are four of them.
It is a violation, not an open question
ADR 0014 already decided this, and was accepted:
Each module is an independent package that declares its dependencies and consumes them from the private registry, including the mesh's own shared library. A cross-package change is therefore two steps: publish the producer, then consume it.
So a git dependency at a pinned commit is not an alternative mechanism under consideration. It is the mesh's own shared library being consumed by a means the record rules out, and the lock naming a sibling directory is what that looks like when nobody publishes.
Which makes the fix a direction rather than a discussion: publish the SDK to the private registry, consume it by version, and the lock stops being able to name a path that exists on one machine.
Open questions
- Which private registry, and does the bootstrap have one? The catalogue holds
verdaccio; a git host typically serves package registries too. ADR 0014 says the private registry as though there is one, and today a fresh mesh has neither until something installs it — so the first SDK build happens before the registry the record assumes. - Or should the SDK be a published package? The catalogue holds a private registry module, and a published package is how the rest of the world does this — at the cost of a mesh needing that registry up before it can build anything, which is a bootstrap problem where there is currently none.
- What generates the lock, and on what? A lock produced on a workstation with sibling checkouts will keep saying this. A lock produced the way the image builds would not.
How this would be checked
| Rule | Checked by |
|---|---|
| A build does not depend on the machine it runs on | The toolchain image builds with npm ci rather than npm install, which refuses a lock that disagrees with its manifest. |
| The SDK a module compiles against is the one named | The commit baked into the toolchain image is compared with the one the manifest pins. |