From d697c6f776c78fa5ae423d522d328a027cf28ecb Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 22 Sep 2026 23:45:49 +0200 Subject: [PATCH] Issue 093: the successor proxy cannot serve what the predecessor still serves, so no web module can migrate one at a time --- .../00-report.md | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 04-ISSUES/093-the-successor-proxy-cannot-serve-what-the-predecessor-still-serves/00-report.md diff --git a/04-ISSUES/093-the-successor-proxy-cannot-serve-what-the-predecessor-still-serves/00-report.md b/04-ISSUES/093-the-successor-proxy-cannot-serve-what-the-predecessor-still-serves/00-report.md new file mode 100644 index 0000000..babf6bb --- /dev/null +++ b/04-ISSUES/093-the-successor-proxy-cannot-serve-what-the-predecessor-still-serves/00-report.md @@ -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 +``` + +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?