ADR 0121: keep distribution, retire only verdaccio; node-* seats migrated #146

Merged
jschoubben merged 1 commits from design/0121-keep-distribution-fix into main 2026-09-27 12:36:54 +00:00
@@ -81,15 +81,18 @@ closed set stays what its name says it is: the *system's* roles, not everyone's.
- **`the-uplink` → `node-uplink`** ([ADR 0117](0117-a-machines-uplink-is-a-seat.md)). Unheld, so it
renames with no migration.
- **The registry seats — `the-artifact-store`, `npm-package-registry` (→ `mesh-artifact-store`,
`mesh-npm-package-registry`) — and `git` (→ `mesh-git`) — are decided but gated.** They are
entangled with consolidating every registry onto gitea (below), so their final shape is settled
when that lands, not renamed in isolation first.
`mesh-npm-package-registry`) — and `git` (→ `mesh-git`) — are decided but deferred.** They each
*deliver* a provision, so renaming them is a delivering-seat migration: a holder that stops
resolving mid-flight takes a provision away from every consumer. That risk is not worth carrying in
the same pass as the node-* renames, so they keep their names until done deliberately.
**The registry consolidates onto gitea.** The mesh should have **one** registry: gitea serving the
container/OCI images, the npm packages, crates, and trivial-tarball artifacts. `distribution` (the
standalone OCI registry) and `verdaccio` (a second npm registry) are retired once gitea serves what
each did. This is recorded here because it reshapes the registry seats; it is **not** a rename and
**not** surgical — see Consequences.
**`distribution` stays the mesh's registry; only `verdaccio` is retired.** An earlier draft of this
record had the registry consolidating onto gitea and `distribution` retired — that was reversed:
`distribution` is the standalone OCI registry serving every `artifact-store://…@sha256` image (the
control plane's own included), and the mesh keeps it. `verdaccio` was a *second* npm registry;
gitea already provides `npm-package-registry`, so verdaccio is redundant and is removed. It is only
in the catalogue (never registered in the running mesh), so removing it is deleting the module — no
migration, nothing to strand.
## Consequences
@@ -104,15 +107,16 @@ each did. This is recorded here because it reshapes the registry seats; it is **
(`mesh-store`→postgres, `mesh-broker`→amqp, the registry seats) that is a mesh-wide provision
outage, the same failure mode as a schema change hitting an old manifest. So: the non-delivering
`node-*` seats and `mesh-build-machine` migrate as one tested controller+catalogue change;
`node-uplink` is free (unheld); the delivering registry seats wait for the gitea consolidation.
- **Retiring `distribution` is blocked until gitea serves images, and is the mesh's highest-risk
operation.** Every image — the control plane's own, the builder's, every module's — is
`artifact-store://…@sha256` served by `distribution`. gitea today provides only `npm-package-registry`
and `git`; it has no OCI registry. Removing `distribution` before gitea serves images strands every
image: nothing pulls, nothing reconciles, and the control plane cannot recover itself. The order is
fixed: stand up gitea's container registry → gitea `provides artifact-store` and holds the seat →
repoint the builder to push there → migrate or re-push existing images → **only then** retire
`distribution` and `verdaccio`. Recorded here so the sequence is not skipped.
`node-uplink` is free (unheld); the delivering registry seats are deferred to their own pass.
- **The node-* migration was done as one controlled step, and it froze briefly.** Deploying the new
controller made it reject the still-old-named claims in the stored manifests, so composition stopped
for the affected nodes until each manifest was re-registered under its new name; running services
were untouched, and the window was seconds. This is the coordinated-migration cost named above,
paid once — and the reason the *delivering* registry seats, whose freeze would be a provision
outage rather than a compose pause, are not folded into the same pass.
- **`distribution` is not retired.** It stays as the registry; only `verdaccio` (a redundant second
npm registry) is removed. The mesh keeps one OCI registry (`distribution`) and gitea for npm/git —
the "one registry, on gitea" idea was considered and dropped.
- **The private network stops pretending to be swappable per node.** The gain is a coherent
server/client model matching how the controller already composes configuration; the cost is that
choosing a different VPN is now a mesh-wide change, not a per-node one — accepted.