# 142 — the mesh can now build and publish its own host *2026-09-30. Both of ADR 0141's named gaps are closed; the host is not yet placed by the mesh.* ## What ADR 0141's insight named, and what each cost > The remaining work is a way to build the host and a way to name a version in a path, and until both > exist nothing delivers a version and every machine takes the fallback. **1. Nothing could compile it.** The toolchain list was a closed set of typescript and python, and its own warning — every language is another implementation of the contracts modules share, so adding one commits to keeping N implementations in step — does not attach to Go. Go is how the host, the control plane and the builder are written, and none of them is a module in that sense: the host is what *applies* modules. Closed by a Go toolchain naming a new base module, `mesh-tools-go`. Named and not pinned, so the mesh answers with the copy it holds and moving compiler is a build rather than an edit to the control plane's source ([ADR 0044](../../02-DECISIONS/0044-a-public-name-is-provisioned-like-any-capability.md), [0142](../../02-DECISIONS/0142-the-mesh-delivers-its-own-components-as-binaries.md)). **2. A version could not reach the path.** An archive named a fixed path and nothing interpolated the build into it, so nothing could ask for `…/versions//`. Closed by `${version}` in any value of a resource that uses an archive or a bundle. **The version is the artifact's digest, short, and not the commit**: two builds of one commit are meant to be the same bytes — the toolchains are `-trimpath` for that — so a content-addressed version means an unchanged build resolves to the path it already had, where a commit-named path would move for an identical binary and recreate everything reading it. ## Three more things were in the way, and none was in the record Found by doing it, in the order they appeared: - **`sourcesFor` turned every entrypoint into a `.ts` file.** One language's file extension, written into the code that serves every language. The extension is the toolchain's now. - **The output directory was left to the compiler.** `tsc --outDir` makes one; `go build -o` writes into a directory and does not create it, failing with a message about a path rather than about a build. Made for every toolchain, because which compilers are forgiving is not something a reader should have to know. - **A bundle was refused if it named what it is built from.** The reason — a bundle is the module's own directory compiled whole — holds for an interpreted language and cannot hold for a compiled one: a Go repository carries several commands, the host and its bootstrap among them, and "the module's own directory" is then not a package at all. A compiled bundle may now say which package; the refusal stands for every interpreted one. And a fourth, in the base module itself: its first Dockerfile ran `apt-get`, and the golang image the mesh holds is Alpine. That is [issue 136](../136-a-module-may-name-a-program-the-machine-does-not-have/00-report.md) in an image rather than on a machine, and the build refused rather than a module failing later — which is the behaviour that issue wants. ## Measured: the mesh compiles its own host and publishes it to its own registry ``` $ mesh-controller build host-arch bundle artifact-store://mesh-host/host-arch/blobs/sha256:ad62528c… mesh-host 1, built on novox from b5196e97 ``` Fetched from the mesh's registry and opened: ``` mesh-host: ELF 64-bit LSB executable, x86-64, statically linked, stripped $ ./mesh-host help mesh-host — the node host ``` Statically linked matters: what a machine holds is a file rather than a container, so a binary needing a libc it did not bring is a delivery that works until a machine differs. **The host is a module now**, with one bundle for `arch` built from `cmd/mesh-host`. A system is required for a compiled artifact because a binary is pinned at link time so a host refuses to touch a machine it was not built for ([ADR 0005](../../02-DECISIONS/0005-the-node-host.md)); `arch` is what all four of this mesh's machines report themselves to be, and another system is another artifact and another build. ## What is left **The host module declares no resources**, so nothing places the built bundle on a machine yet. That is the next piece and it is the one with the interesting question in it: the resource is an archive unpacked to `…/versions/${version}/`, applied by the host that is running, and the bootstrap is not circular because the two are different versions ([ADR 0141](../../02-DECISIONS/0141-the-host-delivers-its-own-successor.md)). The host half of that mechanism — versions side by side, the newest runs, the running one stands aside between reconciles, rollback picks a directory — is built and tested and has never had a version to work on. **One thing worth noticing while writing it.** The systems list exists because "the difference between two of them is a C library, not a kernel" — and a static Go binary has no C library. So one build would in fact run on all three. The pin is then a policy (a host refuses a machine it was not built for) rather than a necessity, which is a reasonable thing to keep and is worth knowing is a choice. **And a sharper one, asked as a question and worth its own record.** The artifact's system is validated and then read by nothing: it does not reach the compiler, no machine is matched against it, and nothing chooses between two artifacts by it. The host built here is x86-64 because the build machine is, not because anything in the declaration said so — correct for this mesh by coincidence. That is [issue 159](../159-an-artifacts-system-is-checked-and-then-ignored/00-report.md).