Files
hq/03-DESIGN/01-to-be/22-the-work-ahead.md
T
jschoubben 33a00d5656 Adopt the glossary's vocabulary in the mutable design docs
"control plane" -> controller and "substrate" -> foundation throughout
03-DESIGN, 00-META and the README, with 06-the-control-plane.md and
07-the-substrate.md renamed to 06-the-controller.md and 07-the-foundation.md.
The immutable 02-DECISIONS records keep their original wording (and links to
them are unchanged) — a term retired here may still appear there, which the
glossary explains how to read.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
2026-09-16 18:48:52 +02:00

105 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
layer: to-be
status: in-progress
updated: 2026-09-15
decisions:
- 02-DECISIONS/0067-genesis-is-a-pivot.md
- 02-DECISIONS/0074-the-wire-is-specified-not-the-types.md
- 02-DECISIONS/0075-two-stores-and-which-provides-what.md
- 02-DECISIONS/0014-no-npm-workspace.md
---
# The work ahead
Everything decided this cycle and not yet built, in the order its dependencies allow. Each phase
ends at something provable on a running mesh, because a phase that ends at a claim is a phase that
went missing without anything complaining.
## How this is built, and when it is run
**Implemented as code with unit tests, committed per change, and run in the lab ONCE the pieces that
would change the outcome are in place.** The mistake this corrects: repeatedly running a 20-minute
lab against a mesh mid-transformation, debugging paths the next phase deletes. The base-build hang,
for instance, is almost certainly the SDK resolving from a git URL inside a docker build (issue
053) — which Phase 2 removes. Debugging it on the current shape is debugging deprecated code.
So the lab run is the acceptance test at the end of the assembled work, not the tool for finding
each bug. Where a fault can be reasoned out of the code path, it is — reading, not running.
## Phase 0 — folded in
The installer's own regressions (stale carried builder, a diagnostic on the parsed stdout) are
fixed and committed. Whether it reaches a full green run is answered by the final lab run below,
after the phases that change its build path are in — not before.
## Phase 1 — the protocol is one thing, and correct *(mostly done: the drift was dead types)*
**Why here.** The Go controller and the TypeScript SDK disagree about what a grant carries
(`consumer` is the module in one, the node in the other). That is exercised by the installer's own
provisioning — the catalogue's database — so it belongs before more is built on it.
- [x] 1.1 the drift was not live — inspection showed the wire agrees (contributions file; envelope
required headers). The dead types that disagreed are removed, ADR 0074 and doc 19 corrected
- [ ] 1.2 a conformance fixture for the two live cross-language contracts — the event envelope and
the contributions file — checked in both suites, as **prevention** rather than repair
- [ ] 1.3 (deferred) a full per-capability suite when a third language is actually added; not
needed to keep two honest
**Done when.** A fixture pins the envelope and the contributions file, and a change to either side
that breaks agreement fails a test rather than a mesh.
## Phase 2 — the private package registry, and the SDK in it
**Why here.** ADR 0014 says a module consumes its dependencies, the SDK included, from the private
registry. Nothing installs one, so the SDK comes from a git URL (issue 053). Needs the installer
(Phase 0) and gitea.
- [ ] 2.1 gitea provides `package-registry` in full — the endpoints, an account the builder may
publish with
- [ ] 2.2 the builder publishes the SDK there on build, by version
- [ ] 2.3 modules consume it by version; the git URL and the sibling-path lock are gone
- [ ] 2.4 a second language's SDK published the same way, proving the path is not TypeScript-only
**Done when.** A module builds against the SDK resolved from the mesh's own registry, and issue 053
closes.
**Where it stands (2026-09-16).** The decision the bootstrap turned on is settled and recorded
([ADR 0076](../../02-DECISIONS/0076-the-sdk-is-a-published-package.md)): the SDK is a published
package, built on a public base image and published before the toolchain that consumes it; mesh-tools
stays the thin toolchain base but `npm ci`s the SDK by version. On the code, the builder now resolves
a package-registry credential — from a binding the mesh writes or from the environment for a hand-run
or bootstrap build — and injects it into an image build as a buildkit secret, never a layer, so a
token is not baked into the toolchain image. Unit-tested. Still ahead: gitea serving the registry in
full with a provisioner that mints tokens (2.1), the SDK built and published by the mesh (2.2), the
mesh-tools manifest flipped off the git URL to `npm ci` by version (2.3), and the genesis step that
raises gitea and publishes the SDK before the base build. Those close together in one lab run.
## Phase 3 — nothing is special after installation
**Why last.** The hardest and riskiest, and it needs everything above: an installer that completes,
a protocol that agrees, a registry to publish to. Issue 051.
- [ ] 3.1 the store is adopted — raised at genesis, then held as the `postgres` module; one server,
the controller's records and every module's database in it
- [ ] 3.2 the broker is adopted — one `lavinmq`, the `/` vhost for the mesh bus, a vhost per
consumer that requires `amqp`; the second server gone
- [ ] 3.3 an upgrade of each, proven: a store the controller reads from, a broker over the
broker, each with a stated window
- [ ] 3.4 `status` can say the foundation is behind its source, which today it cannot form
**Done when.** A mesh built from bare metal runs one postgres and one lavinmq, and can upgrade
either — so the twelve-module floor has no specialty left in it.
## The through-line
Each phase leaves the mesh more able to describe and rebuild itself, and each ends at a run rather
than a paragraph. The order is dependency, not preference: the installer carries everything, the
protocol is what everything speaks, the registry is what everything is built from, and adoption is
what makes the last two things ordinary.
## The one lab run
After Phases 1–3 are implemented and unit-tested and committed: rebuild the images, **verify each
carries its change**, and run the one-node installer once. All 22 checks green, twice, is the
acceptance test for the whole cycle — not a debugging loop, a proof that the assembled thing works.