Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24

Merged
jschoubben merged 177 commits from reconcile-init-into-main into main 2026-09-05 10:27:11 +00:00
Showing only changes of commit 6330abce5f - Show all commits
@@ -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.