Only a thing built and never run is unassignable

The check read "declares no resources" as "runs nowhere", and those are not
the same. The private network declares no resources either — the control plane
computes them when it composes a machine's declaration — and it is assigned to
every machine that has to reach another one. Refusing it stopped a four-machine
bed at its first assignment.

The signal is narrower: it builds an artifact and places nothing. Made a
function of its own, because a judgement with a wrong answer this expensive
should be testable without a database — nothing guarded it, which is how it
shipped.
This commit is contained in:
2026-09-14 17:32:43 +02:00
parent 68e9a16c57
commit 25d2fe1308
2 changed files with 60 additions and 1 deletions
+16 -1
View File
@@ -906,7 +906,7 @@ func (i *Inventory) runsSomewhere(ctx context.Context, module string) error {
// fault and refusing the assignment here would report it as the wrong one.
return nil
}
if m.Computed != "" || len(m.Resources) > 0 {
if !IsBuildInput(m) {
return nil
}
return fmt.Errorf(
@@ -914,3 +914,18 @@ func (i *Inventory) runsSomewhere(ctx context.Context, module string) error {
"builds and other modules are built on top of, not something a machine runs — "+
"`module list` shows what it produces", module)
}
// IsBuildInput reports whether a module exists to be built and never to be run.
//
// **The signal is that it builds something and places nothing** — not merely that it declares no
// resources. Those are different, and confusing them refused a module the mesh itself ships: the
// private network declares no resources either, because the control plane computes them when it
// composes a machine's declaration, and it is assigned to every machine that has to reach another
// one. Refusing it stopped a four-machine bed dead.
//
// Its own function because it is a judgement rather than a lookup, and a judgement with a wrong
// answer this expensive should be testable without a database.
func IsBuildInput(m catalogue.Manifest) bool {
builds := m.Build != nil && len(m.Build.Artifacts) > 0
return builds && m.Computed == "" && len(m.Resources) == 0
}