67 lines
3.4 KiB
Markdown
67 lines
3.4 KiB
Markdown
---
|
|
status: fixed
|
|
opened: 2026-08-22
|
|
located-in: [mesh-control/internal/catalogue, mesh-catalog/modules/firewall]
|
|
fixed-by: the manifest refuses unknown keys, `from` is the field that scopes a port and it is rendered to nftables, and the firewall module applies it
|
|
amended-design: 0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md
|
|
---
|
|
|
|
# 003 — A firewall rule's `scope:` is read by no code
|
|
|
|
## Symptom
|
|
|
|
Five module manifests declare a `scope:` key on firewall rules. The key is not part of the
|
|
firewall rule type and nothing reads it. Real scoping is expressed by a different field.
|
|
|
|
A manifest can therefore appear to restrict a port and restrict nothing.
|
|
|
|
## Why this matters
|
|
|
|
This is the failure mode [`how-we-build.md`](../../00-META/how-we-build.md) names directly:
|
|
*an unenforced rule is indistinguishable from a wrong one, and costs more, because people
|
|
believe it.* Here it is worse than unenforced — the declaration reads as a restriction, so a
|
|
reviewer checking whether a port is scoped will find that it is, and be wrong.
|
|
|
|
It also says something about the manifest as a whole: an unknown key is accepted silently. Any
|
|
misspelled or invented key behaves this way, and this one was found by reading rather than by
|
|
any check.
|
|
|
|
## Evidence
|
|
|
|
- Five manifests carry the key. Zero code paths consume it.
|
|
- Recorded as an observation on 2026-08-22.
|
|
|
|
## Open questions
|
|
|
|
- Should the manifest reject unknown keys outright? That is the general fix; this is one
|
|
instance of it.
|
|
- Were the five declarations intended to restrict something that is currently open? Each needs
|
|
checking against what the node actually exposes — the declaration cannot be trusted either
|
|
way.
|
|
|
|
## How it is answered
|
|
|
|
*2026-08-31.* Both halves, in Novox Mesh. HAL keeps the fault until its provisioning is switched
|
|
off, which is what this issue is now waiting on rather than a fix of its own — patching `scope:`
|
|
into something that works would mean implementing it twice, in the system being replaced.
|
|
|
|
**The unknown key.** A manifest is parsed strictly: an unknown key is refused with the key named,
|
|
the discipline the host's declaration parser has always had. `scope:` would not survive being
|
|
written today, and neither would a misspelling of anything else. This is the general fix — the
|
|
issue's own observation was that *any* invented key behaved this way, and that the one instance
|
|
was found by reading rather than by any check.
|
|
|
|
**The rule that restricts nothing.** `scope:` is not reimplemented. A module says what it listens
|
|
on and **who may reach it**, and saying from where is required rather than defaulted: a rule with
|
|
no source is open, and must say so rather than appear to restrict something. A machine's whole
|
|
rule set is then derived from every module assigned to it — so there is no second list to keep in
|
|
step, which is the condition that let the first one drift out of use unnoticed.
|
|
|
|
**And it is enforced, which is the part that makes this different from before.** The mesh renders
|
|
the rule set; a service on the node is declared to reflect that file, so replacing it restarts
|
|
what loads it. Proven in the lab against two real ports on a real machine: the declared one
|
|
answers from another machine, the undeclared one does not, and removing the module that wanted the
|
|
port closes it with nobody editing a rule.
|
|
|
|
The design is [`03-DESIGN/01-to-be/08-connectivity.md`](../../03-DESIGN/01-to-be/08-connectivity.md) §4.
|