From 6330abce5f3bd4f7eb1dc13fed3dce7c8f02244f Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 1 Sep 2026 17:21:31 +0200 Subject: [PATCH] =?UTF-8?q?028=20=E2=80=94=20two=20things=20want=20one=20p?= =?UTF-8?q?ort,=20and=20nothing=20says=20so=20until=20the=20machine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found by fixing 027 and pushing again. The declaration is now accepted and the database container still cannot start: the mesh's own store holds 5432 on that machine, and the module publishes 5432. Nothing catches it because the substrate is not a module. It arrives from the bundle before there is a mesh to ask, so the control plane has never heard of the store and does not know it holds a port. Resolution can compare modules with each other and cannot compare one against what the mesh is built on. Nor does it compare modules with each other. A port is exclusive on a machine in exactly the way a claim is, and the mesh has a mechanism for that which ports do not use. It has been met before: the end-to-end test that exercises a real database publishes 5433 rather than 5432, inline, with nothing saying why. That is how a constraint becomes folklore. The open question is bigger than the bug. Whether a module should publish to the machine at all decides how a consumer reaches it, and changes what `serves` means. --- .../00-report.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 04-ISSUES/028-two-things-want-one-port-and-nothing-says-so/00-report.md diff --git a/04-ISSUES/028-two-things-want-one-port-and-nothing-says-so/00-report.md b/04-ISSUES/028-two-things-want-one-port-and-nothing-says-so/00-report.md new file mode 100644 index 0000000..a4676c9 --- /dev/null +++ b/04-ISSUES/028-two-things-want-one-port-and-nothing-says-so/00-report.md @@ -0,0 +1,57 @@ +--- +status: located +opened: 2026-09-01 +located-in: [mesh-control] +fixed-by: +amended-design: +--- + +# 028 — Two things want one port, and nothing says so until the machine + +## Symptom + +The database module cannot start on a machine that runs the control plane: + +``` +Bind for 127.0.0.1:5432 failed: port is already allocated +``` + +The mesh keeps its own store on that machine, from the bundle, and it holds 5432. The module +publishes 5432 too. Everything up to the machine is content: it resolves, it composes, it is +pushed, and it is applied — the container is simply the one resource that fails. + +## Why nothing catches it + +**The substrate is not a module.** It arrives from the bundle a host carries, before there is a +mesh to ask. So the control plane has never heard of `mesh-store` and does not know it holds a +port. Resolution can compare modules against each other and cannot compare a module against the +thing the mesh is built on. + +**And nothing compares modules against each other either.** A port is exclusive on a machine in +exactly the way a claim is — one seat, one display server, one artifact store — and the mesh has a +mechanism for that, which ports do not use. Two modules both publishing 5432 would meet the same +wall, one machine later. + +## It has been met before, and worked around + +The end-to-end test that exercises a real database publishes `5433:5432` rather than `5432:5432`. +The workaround is right there, inline, with no note saying why — which is how a constraint becomes +folklore. + +## What a fix has to settle + +- **Whether a module should publish to the machine at all.** Consumers reach a provider by the + machine's address and the port it *serves*, so publishing is what makes that true. An alternative + is that they reach it on the module's own network by name, and nothing is published — which + changes what `serves` means and is a larger decision than it looks. +- **Where the substrate's ports are written down.** Whatever compares them needs to know what the + bundle holds. The bundle is a list of pinned references; what those containers bind is not in it. +- **What a refusal should say.** *5432 is held by the mesh's own store on this machine* is a useful + sentence. *Port is already allocated*, arriving from a container runtime three layers down, is + not. + +## Not the same as a firewall rule + +`listens` already says which ports a module accepts on, and filtering is computed from it. That is +about what may reach a port from elsewhere. This is about two things on one machine wanting to own +the same one, which `listens` does not model and could not answer.