From 26690d89f1dc17b1a372d23dd966d002c35ff6e6 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 23 Sep 2026 23:40:53 +0200 Subject: [PATCH] The artifact store's seat is one per mesh, and the test says so from the catalogue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review of the registry work found the seat node-scoped: a second `distribution` on another machine resolved cleanly there, and only afterwards did the mesh notice `artifact-store` offered by two nodes, with every consumer elsewhere refusing to choose. A node-scoped requirement with one candidate installs that candidate, so anything that wanted the store beside it would have raised a fresh, empty store on the wrong machine first. The claim is mesh-scoped in mesh-catalog now; this holds the catalogue's manifest to it — a second store anywhere is refused by name, where it is assigned. --- .../catalogue/artifact_store_seat_test.go | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 internal/catalogue/artifact_store_seat_test.go diff --git a/internal/catalogue/artifact_store_seat_test.go b/internal/catalogue/artifact_store_seat_test.go new file mode 100644 index 0000000..4b658e4 --- /dev/null +++ b/internal/catalogue/artifact_store_seat_test.go @@ -0,0 +1,38 @@ +package catalogue + +import ( + "strings" + "testing" +) + +// The artifact store's seat is one per mesh, read from the catalogue beside this checkout. +// +// **A second store anywhere is refused by name, not discovered as a consumer failure.** The seat +// was node-scoped, so a second `distribution` on another machine resolved cleanly there — and a +// node-scoped requirement with one candidate installs that candidate on the node, so anything that +// required the store's presence beside it would have raised a fresh, empty store on the wrong +// machine. Only afterwards did the mesh notice: `artifact-store` offered by two nodes, and every +// consumer elsewhere refusing to choose. The claim says it first, where the second store is +// assigned. +func TestASecondArtifactStoreAnywhereIsRefusedByName(t *testing.T) { + store := catalogueManifest(t, "distribution") + + // The first store resolves as it always has. + if _, err := Resolve(shelf(store), []string{"distribution"}, workstation(), World{}); err != nil { + t.Fatalf("the store alone does not resolve: %v", err) + } + + // A second one, on any other machine, is refused — and the refusal names the seat. + elsewhere := World{Held: []Held{{Claim: "the-artifact-store", Scope: ScopeMesh, + Node: "anchor", Module: "distribution"}}} + other := workstation() + other.Name = "laptop" + _, err := Resolve(shelf(store), []string{"distribution"}, other, elsewhere) + if err == nil { + t.Fatal("a second store was accepted on another machine; it would offer artifact-store a " + + "second time and every consumer elsewhere would refuse to choose") + } + if !strings.Contains(err.Error(), "the-artifact-store") || !strings.Contains(err.Error(), "one per mesh") { + t.Fatalf("refused without naming the seat: %v", err) + } +}