ADR 0014 is accepted and unambiguous: each module consumes its dependencies from the private registry, the mesh's own shared library included, and a cross-package change is publish then consume. So the git dependency at a pinned commit is not a mechanism under consideration. It is the shared library being consumed a way the record rules out, and the lock naming a sibling directory is what that looks like when nobody publishes. Issue 053 is reclassified from a question about mechanism to a violation with a direction. What stays open is narrower and real: which software serves the private registry, and that a fresh mesh has none when the first SDK is built — ADR 0014 assumes one exists, and at genesis nothing has installed it. Recorded after arguing at length for a bespoke content-addressed alternative, against a decision that was already made and that I had not read. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
3.7 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design |
|---|---|---|---|---|
| open | 2026-09-15 |
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. |