A container's environment follows a moved port, as a file already does (hq issue 088) #46

Merged
jschoubben merged 2 commits from feat/forge-address into main 2026-09-22 21:30:06 +00:00
Owner

Merge after mesh-catalog#40, which this branch's test reads.

${port:N} resolved only inside file resources, so a module that wrote its own address into a container's environment named a port the mesh may have moved. That address is wrong on any node where the machine port differs, which is most of them, and wrong for a second reason once a node is given that port as a setting.

  • The substitution now reaches a container's environment, with the same guard: a port the module never declared it listens on is refused, naming the container and the variable.
  • The environment map comes from the manifest and resources are shallow-copied, so filling a value in place would have written one node's port into the catalogue for every node after it. The fix builds a fresh map, and only when something changes. There is a test that renders twice with different ports from one manifest.
  • Inert on today's catalogue: exactly one environment value in all 70 manifests uses the placeholder, the one mesh-catalog#40 adds. Addresses on the runtime's own network and bind addresses contain no placeholder and are untouched.

Reviewed independently; the one finding was a test that compared a map with itself, now comparing identity.

Known and not fixed here: ${bound:…} and ${machine:…} still pass through a container's environment as literals rather than being refused, and args/command remain literal-only. Both recorded for hq.

go build ./... && go vet ./... && go test ./... green.

Merge after mesh-catalog#40, which this branch's test reads. `${port:N}` resolved only inside file resources, so a module that wrote its own address into a container's environment named a port the mesh may have moved. That address is wrong on any node where the machine port differs, which is most of them, and wrong for a second reason once a node is given that port as a setting. - The substitution now reaches a container's environment, with the same guard: a port the module never declared it listens on is refused, naming the container and the variable. - The environment map comes from the manifest and resources are shallow-copied, so filling a value in place would have written one node's port into the catalogue for every node after it. The fix builds a fresh map, and only when something changes. There is a test that renders twice with different ports from one manifest. - Inert on today's catalogue: exactly one environment value in all 70 manifests uses the placeholder, the one mesh-catalog#40 adds. Addresses on the runtime's own network and bind addresses contain no placeholder and are untouched. Reviewed independently; the one finding was a test that compared a map with itself, now comparing identity. Known and not fixed here: `${bound:…}` and `${machine:…}` still pass through a container's environment as literals rather than being refused, and `args`/`command` remain literal-only. Both recorded for hq. `go build ./... && go vet ./... && go test ./...` green.
jschoubben added 2 commits 2026-09-22 21:30:01 +00:00
${port:…} answered only inside a file's content, and the one place a module
routinely writes its own address is a container's `env` — where the literal is
wrong on every node whose assignment differs from the manifest's number, and
wrong again on a node given that port as a setting (ADR 0100). Nothing checked
it: the value is a string like any other, and it fails at runtime, on one node.

Filled by the control plane, like a bound value: a port is not secret, so there
is nothing for the host to be the only witness of and it learns no new field.
That is the line ADR 0086 draws — its objection is to a secret being in an
environment at all, not to who fills one in — so a port crosses it and a
credential still does not. Same guard as before: a port the module never said it
listens on is refused, now naming the container and the variable.

The env map is the catalogue's, shared by every node running the module, and the
resource around it is a shallow copy, so a filled value goes into a fresh map —
otherwise the first node composed writes its own port into the manifest and
every node after it is told that one.

Inert on the catalogue as it stands: ${port:…} is written in one other place in
it, a file. Renamed off _files, which this no longer is.
jschoubben merged commit 91a41b7d20 into main 2026-09-22 21:30:06 +00:00
jschoubben deleted branch feat/forge-address 2026-09-22 21:30:06 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-controller#46