113 lines
7.0 KiB
Markdown
113 lines
7.0 KiB
Markdown
---
|
|
topic: the mesh
|
|
status: accepted
|
|
date: 2026-09-22
|
|
deciders: jochen
|
|
reconstructed: false
|
|
extends: 02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md
|
|
---
|
|
|
|
# 103. What an adopted node holds, and what its guard refuses
|
|
|
|
## Context
|
|
|
|
[ADR 0100](0100-a-node-in-use-is-adopted-before-it-is-converged.md) holds a found file or
|
|
container until its module is taken. It also has the mesh guard the store's port and the
|
|
broker's management port with a table that only refuses. Two independent reviews of the build
|
|
found both rules drawn too narrowly and, for the guard, in the wrong place:
|
|
|
|
1. **Other kinds of resource reach what was found.** An untaken module's directory is re-owned
|
|
and re-moded if a predecessor's directory is already at its path, and a database refuses to
|
|
start on a data directory whose mode changed. A service of the same name as a predecessor's
|
|
unit is started, stopped or re-enabled. An action run *in* a held container runs inside the
|
|
predecessor's service. A container that is not found under its own name is created, and can
|
|
mount the predecessor's data beside the predecessor's own container.
|
|
2. **The guard's two ports are not the only ones a found firewall misses.** A published
|
|
container port is forwarded, not received, and a firewall that filters only incoming traffic
|
|
never sees it (ADR 0100's own Context). The broker's plaintext port is published on every
|
|
interface and admitted by the filter from the private network only. So on an adopted node it
|
|
is reachable from anywhere. The same holds for any published port a module restricts to the
|
|
private network.
|
|
3. **The guard refuses by port alone.** On a machine that routes for others, such as a
|
|
predecessor's private-network hub, a packet for another machine's database port is refused as
|
|
well. And a port the guard refuses for a module that is assigned but not taken may still be
|
|
the predecessor's own, serving the predecessor's other machines.
|
|
|
|
## Decision
|
|
|
|
**Found covers every kind that can reach what the machine already has.** On an adopted node,
|
|
for a module not yet taken:
|
|
|
|
- a **directory** present with no record is held: its mode and owner are left, and nothing in it
|
|
is touched;
|
|
- a **service** with no record is held when an administrator installed its unit — the service
|
|
manager reads the unit from outside the packages' own directory — or when the machine uses it,
|
|
running or started at boot. Its state and whether it starts at boot are then left. A reload
|
|
named by the module still happens, since a reload stops nothing
|
|
([ADR 0102](0102-the-mesh-writes-into-a-shared-file-never-over-it.md)). A unit a package merely
|
|
ships that nothing runs and nothing enables is not found: the private network's own tunnel unit
|
|
is one, and holding it kept the private network from ever coming up;
|
|
- an **archive** whose target is present with no record is not unpacked or re-owned; a
|
|
**process** whose unit file is present with no record is not written over or restarted; a
|
|
**user** that exists with no record keeps its shell and groups;
|
|
- a **container** not found by its name is still held if it would mount a path or a volume that
|
|
is present with no record, because it would share the predecessor's data;
|
|
- an **action** or one-off step run *in* a held container is held until the module is taken.
|
|
|
|
What is held is reported as held and is never removed, as ADR 0100 decides for files and
|
|
containers.
|
|
|
|
**The guard refuses what the found firewall may miss, for taken modules only.** Its ports are
|
|
derived from each *taken* module: every machine port it publishes that the filter would admit
|
|
from the private network only, and the ports its manifest names under `guards` — which is how
|
|
the store's port and the broker's management port are included. Only TCP is guarded. A port of a module that is assigned but not taken is not guarded: it may still
|
|
be the predecessor's. The guard matches only packets addressed to this machine. Traffic the
|
|
machine routes for others is never its business.
|
|
|
|
**An opening already answered by a found rule is not added.** If the found firewall already
|
|
admits what an opening says, the opening is reported as satisfied by the found rule, and the
|
|
mesh adds nothing and later removes nothing. The found firewall treats two rules differing only
|
|
in their action, log setting or comment as one rule, so adding the mesh's would take over the
|
|
operator's. Where the found rule is such a twin but is not a plain allow — a deny, a limit, a
|
|
logged allow — the opening is refused, naming that rule, and nothing is added.
|
|
|
|
**A machine raised adopted stays adopted if genesis is run again.** The installer reads the
|
|
node's mode from what the machine records, not only from the operator's flag. A run without
|
|
the flag on an adopted machine is refused.
|
|
|
|
**What of ADR 0100 this replaces.** ADR 0100's guard refused two ports, the foundation's own,
|
|
checked free at genesis, and could therefore close nothing the machine served. That guard is
|
|
replaced by the one above: a guarded port of a taken module may be one the predecessor served
|
|
more widely, and taking the module narrows it to the private network. Everything else in ADR 0100
|
|
stands, and its rules for files and containers now cover the other kinds listed here.
|
|
|
|
## Consequences
|
|
|
|
- Taking a module can narrow a port the predecessor served to anyone: the guard then refuses it
|
|
from outside the private network, as the module declares. Nothing says so yet
|
|
([issue 086](../04-ISSUES/086-taking-a-module-narrows-a-port-without-saying-so/00-report.md)).
|
|
- An untaken module on an adopted node can come up only beside what was found, never on top of
|
|
it: whatever would share the predecessor's data waits for the cutover.
|
|
- The guard grows with the modules taken, and a module's published private-network port is
|
|
protected on an adopted node the way the derived filter protects it on a converged one.
|
|
- Guarding only taken modules means a foundation port on a node joining adopted is guarded once
|
|
its module is taken, not when it is assigned. Genesis takes the foundation's modules, so the
|
|
control-node's store is guarded from the first push.
|
|
|
|
## How it is checked
|
|
|
|
Unit tests hold the host to holding a found directory, a found service, a found archive, process
|
|
and user, and a container that would mount found data; to not holding a unit nothing runs; to
|
|
deferring an action run in a held container; to adding no opening a found rule answers, and to
|
|
refusing one a conflicting found rule would absorb. They hold the controller to deriving the guard from taken modules'
|
|
private-network published ports, and the guard's text to matching only this machine's
|
|
addresses. The installer's tests hold a re-run without the flag on an adopted machine to a
|
|
refusal. The adoption lab bed asserts that the broker's plaintext port is unreachable from
|
|
outside the private network even with the found firewall admitting it, and that an operator's
|
|
own rule for a port the mesh opens survives the opening being removed.
|
|
|
|
## References
|
|
|
|
- [ADR 0100](0100-a-node-in-use-is-adopted-before-it-is-converged.md),
|
|
[ADR 0102](0102-the-mesh-writes-into-a-shared-file-never-over-it.md)
|