088, 089, 120, 128 and 130 each name a commit that is on main and cites them — the forge's address following a moved port, a route naming its endpoint, a provisioner asking the backend what is there, the hosts file written into a marked block, and undeclaring giving a unit back the state it was found in. Each says it was closed by reading commits rather than by a run, so nobody reads a green that was never measured. 129 stays located on purpose: ca-trust is merged and no machine holds it, so the symptom it opened on is still true everywhere.
54 lines
2.9 KiB
Markdown
54 lines
2.9 KiB
Markdown
---
|
|
status: resolved
|
|
opened: 2026-09-22
|
|
located-in: [mesh-controller internal/catalogue/declaration.go, mesh-catalog (every routed module)]
|
|
fixed-by: mesh-controller bdf965d (a route names the endpoint it serves) with `portOfEndpoint` and `AtPublishedPort` — the contribution carries the endpoint's declared port and the machine-side redirection is applied to it like any other
|
|
amended-design:
|
|
---
|
|
|
|
# 089 — A contributed route names a port the node may have moved
|
|
|
|
## What was observed
|
|
|
|
Found in review of the fix for
|
|
[issue 085](../085-the-packages-port-given-at-genesis-is-not-a-setting/00-report.md), 2026-09-22,
|
|
by reading the controller.
|
|
|
|
A module that wants to be reachable by name contributes a route: the name, and the port on the
|
|
machine that answers it. The proxy that serves the route runs on the machine's own network, so it
|
|
dials that port directly.
|
|
|
|
A module's ports can be moved on one node, either because the mesh assigned a different machine
|
|
port or because the node was given one as a setting
|
|
([ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md)). Every
|
|
other reader follows the move: the container's mapping, the filter, the opening, what the module
|
|
says it serves, and the address consumers are told. **The contribution does not.** Contributions
|
|
are settled without the node's port settings, deliberately — the settling step skips the ports key
|
|
so that a port setting never leaks into a rendered configuration file.
|
|
|
|
So on a node where the port moved, the filter opens the port the module actually listens on, and
|
|
the proxy sends the name's traffic to the port it used to listen on. The module is up, the firewall
|
|
is right, and the name is dead.
|
|
|
|
## Why it matters beyond this instance
|
|
|
|
Every module that contributes a route and has a movable port has this hole, and the mesh is
|
|
otherwise consistent about following a moved port. It appears exactly where the migration needs it
|
|
least: on a node adopted beside a predecessor, where a foundation or application port was moved
|
|
precisely because the predecessor holds the usual one.
|
|
|
|
## Open questions
|
|
|
|
- Should a contribution name a port at all, or only the module, with the port resolved from what
|
|
that module serves on that node?
|
|
- If a contribution keeps a port, should settling apply the node's port mapping to it, while still
|
|
keeping the mapping out of rendered configuration?
|
|
- What should refuse a declaration whose contributed route names a port nothing on that node
|
|
listens on?
|
|
|
|
## Closed
|
|
|
|
*2026-09-29, in a grooming pass rather than by whoever fixed it.* A route names an endpoint rather than a port, and the redirection that turns a declared port into the published one is applied to contributions too. Found by
|
|
reading what the code repositories' commits cite: the fix names this issue and is on `main`. It was
|
|
not re-verified on a machine, and this record says so rather than implying a run that did not happen.
|