"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
105 lines
5.8 KiB
Markdown
105 lines
5.8 KiB
Markdown
---
|
||
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.
|