From 2ca63ae54e1d050a8a2cd5f152be3835cb182f66 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 25 Sep 2026 16:59:04 +0200 Subject: [PATCH 1/2] 117: builder's real package-registry grant deadlocks a genesis bootstrap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing builder's hand-faked package-registry binding tonight (requires: package-registry, a real mesh grant instead of a hardcoded JSON fragment) broke three tests describing a deliberate carried-binding fallback for exactly this: gitea's own image is built by builder, so builder cannot yet hold a real grant from gitea the first time either has to exist. Invisible on novox (already bootstrapped, gitea already live) — real on any genesis from scratch. Fix left in place, tests left failing rather than reverted or hacked, so the gap stays visible. --- .../00-report.md | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 04-ISSUES/117-builders-real-package-registry-grant-deadlocks-genesis/00-report.md diff --git a/04-ISSUES/117-builders-real-package-registry-grant-deadlocks-genesis/00-report.md b/04-ISSUES/117-builders-real-package-registry-grant-deadlocks-genesis/00-report.md new file mode 100644 index 0000000..218bd37 --- /dev/null +++ b/04-ISSUES/117-builders-real-package-registry-grant-deadlocks-genesis/00-report.md @@ -0,0 +1,83 @@ +--- +status: located +opened: 2026-09-25 +located-in: [mesh-catalog modules/builder, mesh-catalog modules/gitea] +fixed-by: +amended-design: +--- + +# 117 — `builder` requiring a real `package-registry` grant deadlocks a genesis bootstrap + +## What was observed + +On the control-node, 2026-09-25, fixing `builder`'s hand-faked `package-registry` binding (a +hardcoded JSON fragment standing in for a real grant, found live-blocking nothing but carrying no +correctness at all — see the migration log's account of the same night). The fix declared +`requires: ["artifact-store", "package-registry"]` on `builder` and let the mesh mint the grant +properly, mirroring how `artifact-store` was already required. + +Running `mesh-controller`'s own test suite against the catalogue as changed surfaced three tests +that pinned a different, deliberate design: + +``` +--- FAIL: TestTheBuildersCarriedPackageBindingTakesThePortFromTheNode +--- FAIL: TestTheBuildersCarriedBindingStartsWhereTheForgeServes +--- FAIL: TestTheBuildersPackageBindingKeepsItsIdentity +``` + +Read together with their own comment in `foundation_manifests_test.go`: + +> The builder carries a binding because at genesis nothing provides `package-registry` to resolve +> one from; the day the forge is a module, the same consumer is told what the forge serves. + +The tests expect `builder` to carry its own `package-binding` resource — a `merge: json` file with +`protected: [provision, from, at, as]`, settable only on `port` via the ordinary settings layers — +matching defaults (`port: 3000`, `scheme: http`, `npm-path: /api/packages/novox/npm/`, `as: +mesh-builder`, `from: gitea`) that agree with what `gitea`'s own `serves.package-registry` declares. +Tonight's fix removed that resource entirely. + +**The dependency this protects against is real, not hypothetical.** `gitea`'s own `module.json` +carries a `build` section — its runtime image is compiled from a Dockerfile via `mesh-tools`'s +build/runtime bases, the same as every other built module. `builder` is what runs that build. So: + +- `builder` now `requires: package-registry`, satisfiable only by `gitea`. +- `gitea` cannot run — cannot exist as a container at all — until `builder` has built its image. + +On novox tonight this is invisible: the mesh is already running, `gitea` is already built and +assigned, and the grant resolves immediately. A genesis bootstrap — a new mesh raised from nothing, +or novox fully re-raised for disaster recovery — hits the order the tests describe: `builder` is +needed to build `gitea`'s image before `gitea` can be assigned, so `builder` cannot yet hold a real +`package-registry` grant, so (as tonight's fix has it) `builder` cannot start. + +## Why it matters beyond this instance + +This is the same shape ADR 0075 already named for the mesh as a whole ("the bootstrap still has no +package registry... that is the same pivot as everything else and it is not solved here") — but it +now has a concrete second collision: the one module capable of building a package-registry +provider's own image would refuse to run before that provider exists, precisely because it was +made to depend on it correctly. + +It is also a near miss worth writing down for its own reason: the fix that broke this was reviewed +against `go build`, the full test suite (which flagged it immediately — three tests, not zero), and +matched an explicitly-stated target design in `22-the-work-ahead.md` written a week earlier. Nothing +about the fix was careless; the deadlock was invisible because the node it ran against had already +crossed the point where it would bite. + +## What is not decided here + +- Whether `builder` should carry both — its own default/fallback binding for when no real grant can + be resolved yet, and a real `requires: package-registry` for when one can — and if so, what + decides which one is live at a given moment. Nothing in this mesh's `requires`/`provides` + resolution currently expresses "this, or a carried fallback if it cannot resolve" for any + provision; this would be the first. +- Whether the fallback belongs on `builder` specifically (matching what the removed tests already + encoded) or is a shape the mesh should offer any module bootstrapping a provider it also depends + on — the "builder builds the thing it needs to ask a favour of" pattern is not unique to + `package-registry` and could recur. +- Whether genesis itself should sequence around this instead (build gitea before granting anything, + with `builder` never resolving `package-registry` during that specific window) rather than the + manifest carrying two shapes of one credential. + +Tonight's `builder` fix (`mesh-catalog modules/builder/module.json`) is left in place — correct for +the steady state, live and working on novox — with the three tests above left failing rather than +reverted or hacked to pass, so the gap stays visible rather than quietly patched over. -- 2.54.0 From 09e502058be831268eac610f28143a209eccf203 Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 26 Sep 2026 14:20:05 +0200 Subject: [PATCH 2/2] Issue 121: builder's real package-registry grant deadlocks a genesis bootstrap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renumbered from 117, which is taken on main by 'a module's own code is a container in one record and a process in another' — two reports claimed the same number and git would not have said so. Scrubbed the node's name and a real registry path; this repository is public. --- .../00-report.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename 04-ISSUES/{117-builders-real-package-registry-grant-deadlocks-genesis => 121-builders-real-package-registry-grant-deadlocks-genesis}/00-report.md (91%) diff --git a/04-ISSUES/117-builders-real-package-registry-grant-deadlocks-genesis/00-report.md b/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md similarity index 91% rename from 04-ISSUES/117-builders-real-package-registry-grant-deadlocks-genesis/00-report.md rename to 04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md index 218bd37..9fae9ff 100644 --- a/04-ISSUES/117-builders-real-package-registry-grant-deadlocks-genesis/00-report.md +++ b/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md @@ -6,7 +6,7 @@ fixed-by: amended-design: --- -# 117 — `builder` requiring a real `package-registry` grant deadlocks a genesis bootstrap +# 121 — `builder` requiring a real `package-registry` grant deadlocks a genesis bootstrap ## What was observed @@ -32,7 +32,7 @@ Read together with their own comment in `foundation_manifests_test.go`: The tests expect `builder` to carry its own `package-binding` resource — a `merge: json` file with `protected: [provision, from, at, as]`, settable only on `port` via the ordinary settings layers — -matching defaults (`port: 3000`, `scheme: http`, `npm-path: /api/packages/novox/npm/`, `as: +matching defaults (`port: 3000`, `scheme: http`, `npm-path: /api/packages//npm/`, `as: mesh-builder`, `from: gitea`) that agree with what `gitea`'s own `serves.package-registry` declares. Tonight's fix removed that resource entirely. @@ -43,9 +43,9 @@ build/runtime bases, the same as every other built module. `builder` is what run - `builder` now `requires: package-registry`, satisfiable only by `gitea`. - `gitea` cannot run — cannot exist as a container at all — until `builder` has built its image. -On novox tonight this is invisible: the mesh is already running, `gitea` is already built and +On the control-node tonight this is invisible: the mesh is already running, `gitea` is already built and assigned, and the grant resolves immediately. A genesis bootstrap — a new mesh raised from nothing, -or novox fully re-raised for disaster recovery — hits the order the tests describe: `builder` is +or that node fully re-raised for disaster recovery — hits the order the tests describe: `builder` is needed to build `gitea`'s image before `gitea` can be assigned, so `builder` cannot yet hold a real `package-registry` grant, so (as tonight's fix has it) `builder` cannot start. @@ -79,5 +79,5 @@ crossed the point where it would bite. manifest carrying two shapes of one credential. Tonight's `builder` fix (`mesh-catalog modules/builder/module.json`) is left in place — correct for -the steady state, live and working on novox — with the three tests above left failing rather than +the steady state, live and working on the control-node — with the three tests above left failing rather than reverted or hacked to pass, so the gap stays visible rather than quietly patched over. -- 2.54.0