Files
jschoubben 5062c36fc9 A binding answered on this very node still carries an address
Two sibling branches resolve a provision answered by the consumer's own machine.
The one for a node-scoped provider falls back to loopback when the machine is on
no private network, with a comment saying why and a test holding it. The one for
a mesh-scoped provider passed node.At straight through, and nothing noticed
because nothing had yet composed a host out of it.

The mesh's own artifact store is mesh-scoped and sits on the same machine as the
builder that pushes to it. Give the builder the address from its binding and it
gets MESH_REGISTRY=:5000 — a name with no host, written into its environment
without complaint. It surfaces much later as

  ":5000/mesh-tools/build" is not a valid repository/tag

which is a message about a tag for a fault in how a binding was resolved, on a
machine several steps from the decision.

A machine off the private network still reaches itself, which is what the
neighbouring branch already said. The test fails without the fix, showing the
empty address rather than only the symptom.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
2026-09-14 21:11:37 +02:00

53 lines
2.2 KiB
Go

package catalogue
import "testing"
// A MESH-SCOPED provider on the consumer's own node must deliver a usable address too.
//
// The sibling case — a node-scoped provider minting no credential — has had this fallback and a
// test for it for some time. This branch did not, and the difference is invisible until something
// puts the address into a string: the mesh's own artifact store is mesh-scoped and lives on the
// same machine as the builder that pushes to it, so the builder's environment was written as
// `MESH_REGISTRY=:5000`. Nothing refused it. The runtime did, several steps later, with
// `":5000/mesh-tools/build" is not a valid repository/tag` — a message about a tag, for a fault in
// how a binding was resolved.
//
// A machine off the private network still reaches itself.
func TestAMeshScopedProviderOnThisNodeStillCarriesAnAddress(t *testing.T) {
provider := Manifest{Module: "registry",
Provides: []Offer{{Name: "artifact-store", Scope: ScopeMesh}},
Serves: map[string]map[string]any{
"artifact-store": {"port": 5000}}}
consumer := Manifest{Module: "builder", Requires: []string{"artifact-store"}}
// No `At`: a mesh with no private network raised, which is every mesh before somebody places
// its nodes on one — including the moment just after it is installed.
got, err := Resolve(
map[string]Manifest{"registry": provider, "builder": consumer},
[]string{"builder", "registry"},
Node{Name: "anchor"},
World{})
if err != nil {
t.Fatalf("a mesh-scoped provision answered on this very node was refused: %v", err)
}
var found *Needed
for i := range got.Needs {
if got.Needs[i].Name == "artifact-store" && got.Needs[i].For == "builder" {
found = &got.Needs[i]
}
}
if found == nil {
t.Fatalf("the store was not delivered to the builder at all: %+v", got.Needs)
}
if found.At == "" {
t.Fatalf("the binding carries no address, so anything composing a host from it gets none: %+v", found)
}
if found.At != "127.0.0.1" {
t.Fatalf("off the private network the address must fall back to loopback, got %q", found.At)
}
if got, want := plainly(found.Serves["port"]), "5000"; got != want {
t.Fatalf("the port was not delivered: got %q want %q", got, want)
}
}