Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -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.
|
||||
Reference in New Issue
Block a user