The mesh runs its own registry, certifies its own names, and computes its own filtering
Issue 003 is answered in both halves: manifests are parsed strictly, and a module says what it listens on and from where rather than carrying a key nothing reads. The design records what was built and how each part is checked. Issue 013 is new, found by reading while writing the first module that has both a computed file and a service that needs it. The file arrived second. It failed, then the next reconcile fixed it, which is why nothing caught it.
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
---
|
||||
layer: to-be
|
||||
status: designed
|
||||
code: []
|
||||
updated: 2026-08-29
|
||||
code:
|
||||
- mesh-control internal/catalogue/filtering.go
|
||||
- mesh-host internal/apply (the service that reflects it)
|
||||
updated: 2026-08-31
|
||||
decisions:
|
||||
- 02-DECISIONS/0005-the-node-host.md
|
||||
- 02-DECISIONS/0004-a-node-and-how-it-joins.md
|
||||
@@ -275,6 +277,50 @@ from a wrong one, and costs more, because people believe it.*
|
||||
([ADR 0005](../../02-DECISIONS/0005-the-node-host.md)), and
|
||||
the one manifests lack. `scope:` survived because nothing rejected it.
|
||||
|
||||
### What was built
|
||||
|
||||
*2026-08-31. Everything above was the intention; this is what exists, and how each part is
|
||||
checked. [04-ISSUES/003](../../04-ISSUES/003-firewall-scope-is-read-by-no-code/00-report.md) is
|
||||
resolved by it.*
|
||||
|
||||
**A module says what it listens on**, as a port, a protocol and a source — `mesh`, `anywhere`, or
|
||||
`machine`. The source is required and there is no default, which is the whole of *a rule names its
|
||||
source*: a manifest that omitted it would read as a restriction and be none. *Checked by a manifest
|
||||
with a port and no source being refused, and by one naming a source the mesh cannot render being
|
||||
refused as well — the second is what stops a source becoming a comment.*
|
||||
|
||||
**The set is derived per node**, from every module assigned to it, not from the module asking for
|
||||
it. Where two modules want the same port, the wider source wins and both are still named, because
|
||||
removing one of them must not read as a reason to close a port the other needs. *Checked by
|
||||
rendering a node whose firewall module has no ports of its own and asserting another module's port
|
||||
is in the result; and by giving one port two modules and one source each, and asserting the
|
||||
narrower rule disappears while both names survive.*
|
||||
|
||||
**What is not declared is closed.** The rule set drops by default. *Checked by naming the input
|
||||
chain in the assertion rather than the policy alone — the first version of that test passed while
|
||||
input accepted everything, because another chain in the same file also said `policy drop`.*
|
||||
|
||||
**From the mesh means the machines the mesh has**, as their addresses on the private network, not
|
||||
as a subnet. A subnet is a guess that stays wrong quietly; the address set shrinks when a node
|
||||
leaves and nobody edits anything. A machine that asks for `mesh` where the mesh knows no addresses
|
||||
is **closed and told so in the file** — widening it would open a port nobody asked to open, and
|
||||
dropping it silently would close one somebody did.
|
||||
|
||||
**Three things it deliberately does not do**, each of which looked right and would have broken
|
||||
something:
|
||||
|
||||
| | why not |
|
||||
|---|---|
|
||||
| decide what the machine **forwards** | the container runtime writes its own forwarding rules and a second policy is consulted alongside them, so a drop here stops every container on the node — the control plane included. Nothing in a manifest says what a machine routes, so there is nothing to derive it from either |
|
||||
| **flush the ruleset** when loading | that empties every table on the machine, the runtime's among them. Only the mesh's own table is replaced, and it is declared empty first so the replacement works on a machine loading one for the first time |
|
||||
| carry a **command to load itself** | the link may not carry an action ([ADR 0005](../../02-DECISIONS/0005-the-node-host.md)). A service is declared to reflect the file instead, so replacing it restarts what loads it — the shape that rule leaves, used here for the first time for its real purpose |
|
||||
|
||||
**And it is enforced, which is what separates this from `scope:`.** Proven on two real machines:
|
||||
two ports opened, one declared, and from the other machine the declared one answers and the
|
||||
undeclared one does not — then the module is removed and the port closes with nobody editing a
|
||||
rule. *A rule set that is written but never loaded passes every check that reads the file, which
|
||||
is why the check reads packets.*
|
||||
|
||||
## 5 — Certificates
|
||||
|
||||
**Two authorities, kept separate on purpose.**
|
||||
|
||||
Reference in New Issue
Block a user