From 9fab0b731a77003513bf15b3177eb8200652b38d Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 10 Sep 2026 21:08:09 +0200 Subject: [PATCH] catalogue: a contribution reaches the port its own machine published, from any machine The co-located fix could not reach a grant assembled for a consumer on another machine: ContributionsFrom never sees a port map, so the proxy was told the workload's software port and dialled a number that machine never published. The consumer's own assignments are fetched where the grant is built and applied there. The same fault as 038, one node over. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF --- cmd/mesh-control/plan.go | 9 +++++++++ internal/catalogue/co_located_test.go | 27 +++++++++++++++++++++++++++ internal/catalogue/declaration.go | 12 ++++++++++++ 3 files changed, 48 insertions(+) diff --git a/cmd/mesh-control/plan.go b/cmd/mesh-control/plan.go index 9cc6cdf..ee41153 100644 --- a/cmd/mesh-control/plan.go +++ b/cmd/mesh-control/plan.go @@ -627,6 +627,15 @@ func grantsFor(ctx context.Context, open *stores, node string) ([]catalogue.Gran if err != nil { return nil, err } + // A port in there is the consumer's software port until this. The consumer is on another + // machine, so the assignment that moved it is that machine's — fetched here rather than + // looked for in this one's, which is the whole reason the co-located fix could not reach + // this case (novox/hq 04-ISSUES/038, the cross-node half). + published, err := portsOn(ctx, inv, s.Consumer, s.ConsumerModule) + if err != nil { + return nil, err + } + values = catalogue.AtPublishedPort(values, s.ConsumerModule, published) from := s.ConsumerModule if !asks { // That module no longer wants this. Left empty, which is what the declaration reads diff --git a/internal/catalogue/co_located_test.go b/internal/catalogue/co_located_test.go index 1417645..4ae577a 100644 --- a/internal/catalogue/co_located_test.go +++ b/internal/catalogue/co_located_test.go @@ -259,6 +259,33 @@ func TestAContributionFromAnotherMachineKeepsItsOwnPort(t *testing.T) { } } +// The cross-node half of the same fault: a grant assembled on the providing machine carries the +// consumer's declared port until the CONSUMER's machine's assignments are applied to it. The +// declaration layer cannot do it — those assignments are not this machine's, which is the line the +// test above holds — so the grant layer is handed them and does it there. +func TestAContributionIsRedirectedToWhereItsOwnMachinePublishedIt(t *testing.T) { + published := map[int]int{3000: 20000} + + got := AtPublishedPort(map[string]any{"name": "git.example.tld", "port": 3000}, "forge", published) + if port, _ := asPort(got["port"]); port != 20000 { + t.Errorf("the proxy would dial a port that machine never published: %v", got["port"]) + } + if got["name"] != "git.example.tld" { + t.Errorf("redirecting the port disturbed the rest of the contribution: %v", got) + } + + // Idempotent, and silent about a port nobody moved: a module that pinned its own mapping has no + // assignment, and must come back exactly as it was written. + again := AtPublishedPort(got, "forge", published) + if port, _ := asPort(again["port"]); port != 20000 { + t.Errorf("applying it twice moved the port again: %v", again["port"]) + } + pinned := AtPublishedPort(map[string]any{"port": 9070}, "office", published) + if port, _ := asPort(pinned["port"]); port != 9070 { + t.Errorf("a port the mesh never assigned was rewritten: %v", pinned["port"]) + } +} + func asStrings(v any) []string { listed, ok := v.([]any) if !ok { diff --git a/internal/catalogue/declaration.go b/internal/catalogue/declaration.go index 7fd0416..a029d65 100644 --- a/internal/catalogue/declaration.go +++ b/internal/catalogue/declaration.go @@ -997,3 +997,15 @@ func atMachinePort(serves map[string]any, module string, ports map[string]map[in copied["port"] = at return copied } + +// AtPublishedPort redirects a contribution's port to where the CONSUMER's own machine published it. +// +// The same redirection as [atMachinePort], for the one caller that cannot reach it. A grant is +// assembled on the providing machine out of a consumer that lives on another one, so that +// consumer's assignments are fetched there and handed in, rather than looked for here where they +// are not. Without it a proxy told to reach a workload on another machine is told the port the +// workload's *software* uses, and dials a number that machine never published — the same fault as +// novox/hq 04-ISSUES/038, one node over. +func AtPublishedPort(values map[string]any, module string, published map[int]int) map[string]any { + return atMachinePort(values, module, map[string]map[int]int{module: published}) +}