Issues 088, 089 and 090, found fixing 085 #76

Merged
jschoubben merged 2 commits from fix/issue-085-followups into main 2026-09-22 20:00:02 +00:00
3 changed files with 134 additions and 0 deletions
@@ -0,0 +1,41 @@
---
status: open
opened: 2026-09-22
located-in: []
fixed-by:
amended-design:
---
# 088 — The forge's own address names a port it may not have
## What was observed
Found while fixing [issue 085](../085-the-packages-port-given-at-genesis-is-not-a-setting/00-report.md),
2026-09-22, by reading the catalogue rather than by running it.
The forge's module declares its own address as an environment value on its container, written out
in full with the port in it. Its container publishes its port without fixing the machine side, so
the mesh assigns that side — which is already, today, usually not the number written into the
address. The address is therefore wrong on any node where the assignment differs, and it becomes
wrong for a second reason once a node is given that port as a setting
([ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md)).
The mesh has the right answer for this: a placeholder that resolves to the port actually in use.
It is substituted in **file** resources only, and this value is in a container's environment map,
where nothing substitutes it.
## Why it matters beyond this instance
Two rules of the mesh meet here and neither is enforced. A module may not name a port it does not
control, and what a module is told about an address must come from what the provider serves. Any
module that writes its own address into an environment value has the same hole, and nothing checks
for it: the value is a string like any other, and it is wrong only at runtime, on the node where
the assignment happens to differ.
## Open questions
- Should the port placeholder resolve in a container's environment as it does in files, or should
a module that needs its own address be made to carry it in a file?
- Should composition refuse an environment value that names a port the module does not fix, the
way it refuses other claims a module cannot make?
- Which other modules write their own address, with a port, into their environment?
@@ -0,0 +1,47 @@
---
status: open
opened: 2026-09-22
located-in: []
fixed-by:
amended-design:
---
# 089 — A contributed route names a port the node may have moved
## What was observed
Found in review of the fix for
[issue 085](../085-the-packages-port-given-at-genesis-is-not-a-setting/00-report.md), 2026-09-22,
by reading the controller.
A module that wants to be reachable by name contributes a route: the name, and the port on the
machine that answers it. The proxy that serves the route runs on the machine's own network, so it
dials that port directly.
A module's ports can be moved on one node, either because the mesh assigned a different machine
port or because the node was given one as a setting
([ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md)). Every
other reader follows the move: the container's mapping, the filter, the opening, what the module
says it serves, and the address consumers are told. **The contribution does not.** Contributions
are settled without the node's port settings, deliberately — the settling step skips the ports key
so that a port setting never leaks into a rendered configuration file.
So on a node where the port moved, the filter opens the port the module actually listens on, and
the proxy sends the name's traffic to the port it used to listen on. The module is up, the firewall
is right, and the name is dead.
## Why it matters beyond this instance
Every module that contributes a route and has a movable port has this hole, and the mesh is
otherwise consistent about following a moved port. It appears exactly where the migration needs it
least: on a node adopted beside a predecessor, where a foundation or application port was moved
precisely because the predecessor holds the usual one.
## Open questions
- Should a contribution name a port at all, or only the module, with the port resolved from what
that module serves on that node?
- If a contribution keeps a port, should settling apply the node's port mapping to it, while still
keeping the mapping out of rendered configuration?
- What should refuse a declaration whose contributed route names a port nothing on that node
listens on?
@@ -0,0 +1,46 @@
---
status: open
opened: 2026-09-22
located-in: []
fixed-by:
amended-design:
---
# 090 — The forge module does not take over the forge genesis raised
## What was observed
Found in review of the fix for
[issue 085](../085-the-packages-port-given-at-genesis-is-not-a-setting/00-report.md), 2026-09-22.
Genesis raises a forge before any module exists, so the mesh has somewhere to keep its own
packages. The intention is that the forge's module later takes that running forge over, the way
the store and the broker are taken over in place
([ADR 0078](../../02-DECISIONS/0078-the-store-and-broker-are-modules.md)).
It cannot, as things stand. The forge genesis raises and the forge the module declares differ in
four ways at once:
- **the container's name** — the module's is not the one genesis used;
- **the network** — genesis runs it on the machine's own network, the module's runs bridged;
- **where its data lives** — genesis gives it no data volume of its own; the module mounts one;
- **the address it is told to call itself** — genesis sets it from the port given; the module
sets none.
Assigning the module therefore does not adopt what is running. It raises a second forge, with a
different name, on a different network, with a different data directory, beside the first.
## Why it matters beyond this instance
Adoption in place is how the mesh is supposed to hand anything genesis raised to the module that
owns it afterwards. It works for the store and the broker because the container's name and its
data are the same on both sides. Nothing checks that a module which is meant to take over what
genesis raised actually can, and the check is not hard to state: same name, same data, same
network, or it is not a takeover.
## Open questions
- Should genesis raise the forge exactly as the module declares it — name, network and data
directory — so the module adopts it by the rule that already exists?
- Should something refuse to call a module the successor of a bootstrap service it cannot adopt?
- Is the forge's own address better resolved than set, which is [issue 088](../088-the-forges-own-address-names-a-port-it-may-not-have/00-report.md)?