route-adapter: provide route by writing into the predecessor's proxy (hq ADR 0104) #42

Merged
jschoubben merged 1 commits from feat/route-adapter into main 2026-09-22 22:12:49 +00:00
Owner

Implements hq ADR 0104, which decides issue 093: during a migration, a provision whose only provider owns a scarce machine-wide resource may be answered by an adapter that writes into the predecessor's own configuration.

This module provides route without binding anything. It receives the same contributions the mesh's proxy would and writes one route file per name into the predecessor's dynamic directory, pointing at the machine port the contributing module publishes, using the predecessor's own certificate resolver so no new certificate is requested. The predecessor's proxy keeps serving every name it already serves; a name whose module has migrated is served by the same proxy, pointing at the mesh's container.

Safety, both tested: a file is the module's only if its name matches its pattern and its first line carries its marker. It removes only those and leaves everything else, including a lookalike it did not write. Files are staged and renamed so the proxy never reads a half-written one, and a name that is not a plain hostname is refused rather than turned into a path.

Per-node settings for the predecessor's directory, entry point, certificate resolver and how the proxy reaches the machine.

Known gap, stated rather than hidden: a bind mount's host side cannot follow a node setting today, so if the directory setting names somewhere other than the mount, the module refuses on its first pass and says so, rather than writing where nothing reads. The general fix is a per-node path reaching a container's volumes, the way ports do, and that is a decision for hq rather than for a module with a stated end.

It is migration scaffolding: assigned only on an adopted node, and removed when the predecessor's proxy retires. The README says so, including the one thing it cannot do for itself: when a module is taken, the predecessor's own route file for that name has to go, or two routers claim one host rule.

Tests: 8, green. The controller's catalogue tests pass against this manifest, including the gate that every mount is declared.

Implements hq ADR 0104, which decides issue 093: during a migration, a provision whose only provider owns a scarce machine-wide resource may be answered by an adapter that writes into the predecessor's own configuration. This module provides `route` without binding anything. It receives the same contributions the mesh's proxy would and writes one route file per name into the predecessor's dynamic directory, pointing at the machine port the contributing module publishes, using the predecessor's own certificate resolver so no new certificate is requested. The predecessor's proxy keeps serving every name it already serves; a name whose module has migrated is served by the same proxy, pointing at the mesh's container. Safety, both tested: a file is the module's only if its name matches its pattern **and** its first line carries its marker. It removes only those and leaves everything else, including a lookalike it did not write. Files are staged and renamed so the proxy never reads a half-written one, and a name that is not a plain hostname is refused rather than turned into a path. Per-node settings for the predecessor's directory, entry point, certificate resolver and how the proxy reaches the machine. **Known gap, stated rather than hidden:** a bind mount's host side cannot follow a node setting today, so if the directory setting names somewhere other than the mount, the module refuses on its first pass and says so, rather than writing where nothing reads. The general fix is a per-node path reaching a container's volumes, the way ports do, and that is a decision for hq rather than for a module with a stated end. It is migration scaffolding: assigned only on an adopted node, and removed when the predecessor's proxy retires. The README says so, including the one thing it cannot do for itself: when a module is taken, the predecessor's own route file for that name has to go, or two routers claim one host rule. Tests: 8, green. The controller's catalogue tests pass against this manifest, including the gate that every mount is declared.
jschoubben added 1 commit 2026-09-22 22:12:43 +00:00
A node being adopted cannot take a web module: every module reachable by
name requires route, the mesh's only provider of it binds the two public
ports, and the predecessor's proxy holds them and serves every public
name there. Stopping the predecessor to break the circle darkens every
name at once, with every certificate to re-obtain in the same window.

So this answers the same provision without binding anything. It provides
route and receives the same contributions file, and writes each
contribution as one route file where the predecessor's file provider
reads, naming the predecessor's own certificate resolver so no
certificate is asked for. It removes a file it wrote when its
contribution goes and never touches a file it did not write — the name
and a marker inside both have to say it is the mesh's.

A step, not a daemon: run-once, re-run by restart-on over the received
file and the settings. The predecessor's dynamic directory is a node
setting, because it is a fact about one machine.

Migration scaffolding with a stated end: assigned only on an adopted
node, deleted when the predecessor's proxy retires.
jschoubben merged commit 176bbd6085 into main 2026-09-22 22:12:49 +00:00
jschoubben deleted branch feat/route-adapter 2026-09-22 22:12:49 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-catalog#42