The correction the operator pushed: stop running a 20-minute lab against a mesh mid-transformation, debugging paths the next phase deletes. The base-build hang is almost certainly the SDK resolving from a git URL inside a docker build (issue 053), which Phase 2 removes — so debugging it on the current shape is debugging deprecated code. Phase 0 folds in: the installer's own regressions are fixed and committed; whether it runs green is the final acceptance test, after the phases that change its build path are in. Faults that can be reasoned out of the code path are, by reading rather than running. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
93 lines
4.7 KiB
Markdown
93 lines
4.7 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
|
||
|
||
**Why here.** The Go control plane 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.
|
||
|
||
- [ ] 1.1 extract the wire contracts to one specification the two implementations both conform to
|
||
- [ ] 1.2 make Go and TypeScript agree — one meaning for `consumer`, the envelope's six headers
|
||
emitted by both
|
||
- [ ] 1.3 an executable conformance suite, per capability, both existing SDKs made to pass it
|
||
- [ ] 1.4 the `x-schema` header written, so a body's shape can version (ADR 0074)
|
||
|
||
**Done when.** A fixture emitted by one implementation is read identically by the other, checked in
|
||
both test suites.
|
||
|
||
## 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.
|
||
|
||
## 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 control plane'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 control plane reads from, a broker over the
|
||
broker, each with a stated window
|
||
- [ ] 3.4 `status` can say the substrate 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.
|