Issue 093: the successor proxy cannot serve what the predecessor still serves #80
+64
@@ -0,0 +1,64 @@
|
||||
---
|
||||
status: open
|
||||
opened: 2026-09-22
|
||||
located-in: []
|
||||
fixed-by:
|
||||
amended-design:
|
||||
---
|
||||
|
||||
# 093 — The successor proxy cannot serve what the predecessor still serves
|
||||
|
||||
## What was observed
|
||||
|
||||
On the control-node, hours after it was adopted, 2026-09-22.
|
||||
|
||||
Assigning the first web module to the adopted node was refused:
|
||||
|
||||
```
|
||||
nothing provides "route", wanted by <module>
|
||||
```
|
||||
|
||||
Every module that must be reachable by name requires a **route**, and the mesh has one provider of
|
||||
it: its own proxy. That proxy runs on the machine's own network and binds the two public ports
|
||||
directly. It declares no port mapping, so a node's `ports` setting cannot move it
|
||||
([ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md) moves a
|
||||
*published mapping*). The predecessor's proxy holds those ports and serves every public name on
|
||||
the machine. The two cannot run at once.
|
||||
|
||||
So there is a circle:
|
||||
|
||||
- a web module cannot be taken until the mesh's proxy runs;
|
||||
- the mesh's proxy cannot run until the predecessor's stops;
|
||||
- when the predecessor's stops, **every name it serves goes dark** — because the mesh's proxy
|
||||
serves only what mesh modules contributed, and the predecessor's services are not modules yet.
|
||||
|
||||
Adoption was built for exactly this shape and does not cover it. It keeps a **file** as it was and
|
||||
a **container** as it was, holding each until its module is taken. It has nothing to say about a
|
||||
service whose successor is *different software*: the predecessor's proxy and the mesh's read
|
||||
different configuration and share no container name, so there is nothing to hold — only something
|
||||
to replace, all at once, for every name at the same moment.
|
||||
|
||||
## Why it matters beyond this instance
|
||||
|
||||
The proxy is the first case, not the only one. Any provision with exactly one provider that owns a
|
||||
scarce machine-wide resource has this shape: a resolver on port 53, a mail relay on 25, a
|
||||
certificate authority. The migration's rule — one service at a time, each when its data has moved
|
||||
— holds only while the successor can stand beside the predecessor. Where it cannot, the mesh
|
||||
currently offers no way to take one step at a time.
|
||||
|
||||
It also decides the migration's order. The runbook had the proxy last, as the tidy final cutover.
|
||||
It has to be first, because everything reachable by name waits on it.
|
||||
|
||||
## Open questions
|
||||
|
||||
- Should the mesh's proxy be able to serve routes it did not derive — a predecessor's names, given
|
||||
to it as the operator's own configuration, each disappearing when the module that owns that name
|
||||
contributes its route? That keeps the predecessor's configuration alive under the mesh's proxy,
|
||||
which is what adoption promises everywhere else.
|
||||
- Or should a provision be satisfiable by an **adapter**: a module that provides `route` by writing
|
||||
into the predecessor's proxy, so modules migrate one at a time while the predecessor still
|
||||
serves, and the proxy itself is taken last?
|
||||
- What becomes of the certificates in either case? The predecessor holds them; the successor would
|
||||
otherwise ask a public authority for every name at the moment of the cutover.
|
||||
- Is there a general rule here for "a requirement whose only provider owns a scarce port", or is
|
||||
each such provision its own decision?
|
||||
Reference in New Issue
Block a user