Files
hq/04-ISSUES/094-a-port-published-as-the-machine-side-cannot-be-moved/01-diagnosis.md
T
jschoubben 235b9ea0e5 Issues 096 and 097, and 094 diagnosed: a setting stored where it cannot work, and a resource that changed target
094's cause is one blind spot read from two ends, written up in its diagnosis; the fix
answers the first open question and not the other two, which become 096. 097 was found
looking at what the forge's cutover left running.
2026-09-23 02:20:48 +02:00

3.5 KiB

Diagnosis — 2026-09-23

One cause, two symptoms

Both halves of the report come from the same blind spot, in two different places.

The check that refused the setting collected, for each entry a container publishes, only its last segment. A short form publishes one number, which is the container's port and the machine's at once, so reading the last segment is right. A long form — a machine port mapped to a different port inside the container — has two, and the last segment is the container's. So the machine side, the number the module names in listens, in serves and in every port substitution, was not in the set of ports the module was considered to publish, and giving it one was refused as naming nothing.

The lookup that made naming the other half useless reads the same map under two different keys. Everything derived from what the module declares — the filter, the openings, the guard, what a consumer is told, a port substituted into a file — looks the machine side up. The one reader that rewrites the mapping handed to the container runtime looks up the container's port. For a short form those are the same number and no one notices. For a long form they differ, so exactly one reader ever found the entry: keyed the only way the check allowed, the container's mapping moved and nothing else did, leaving a firewall, a set of openings and a consumer all pointing at a port the software had left.

That is also the third symptom in the report, seen from the other end. No opening was derived for the moved port because the opening is derived from the declared port, which still read as the old number; and a per-node expose could not rescue it, because expose keys on the same declared port — it widens the opening on the port nothing is on any more, and naming the real machine port is refused as a port the module does not listen on.

What was ruled out

The openings derivation itself. Composed with no setting at all, a module publishing a long-form mapping on an adopted node does get its opening, on the machine side, forwarded to the container's port. A regression test now records that, deliberately passing before the fix as well as after, so the next reader does not go looking there.

Answering the first open question

Either end names the mapping, and both answer. A module publishing "2222:22" may reasonably say it listens on the port its software uses or on the port the machine serves; the mesh accepts whichever the setting names and returns the machine port under both, so every reader finds the same number under the key it happens to hold. This keeps working what already worked — the container's end was the only key the old check accepted — and makes it mean the same thing.

Ambiguity is refused where it is real: one number naming two different mappings, and the two ends of one mapping given two different machine ports. Naming both ends of one mapping with the same number was already refused, by the rule that a machine port has one holder.

What this does not close

The second and third open questions stand, and they are the push-blocking half: the setting is still stored without a manifest in view, so a key that names nothing a module publishes is accepted where it is set and refused at composition — where it stops the node being told anything at all, rather than stopping that module. The fix removes one reason a key could be wrong; it does not remove the shape of the failure. Carried to issue 096.