From a87308814060bf7da7735f74f32b2e672e124f92 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 23 Aug 2026 23:43:09 +0200 Subject: [PATCH] A worked example: the whole model applied to an ordinary mesh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shape research 004 identified — one machine with a routable address, one publicly named but behind a household connection, one stationary on that network, one that roams — written out with every field the model has, in role names and documentation addresses. It shows the ISP modem doing nothing, because in bridge mode it is a media converter: it changes the physical medium and leaves the packets alone, so it creates no IP-level fact and appears nowhere. In router mode it would be a second gateway and publishing would need a rule on both, which is the one case the model still cannot express. It shows two segments sharing one gateway declaration, which means one gateway machine, and a policy rule between them that is asymmetric because useful ones almost always are. And it shows what is deliberately absent. Research 004 recorded overlay addresses, hub election and names for exactly this topology, and none of them appear: a scenario must not state what the mesh is responsible for. Given the declaration, whether a hub is elected, whether the NATed machine's endpoint is learned, and whether the roaming machine re-forms after moving are all observed rather than arranged. The absence is the point. The run at the end moves one identity through four positions — home, foreign network, asleep, home again — against a foreign gateway whose mapping expires in 30 seconds, which is why a number is there rather than a boolean. --- 03-DESIGN/01-to-be/02-scenario-declaration.md | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/03-DESIGN/01-to-be/02-scenario-declaration.md b/03-DESIGN/01-to-be/02-scenario-declaration.md index 62e59b2..5789e4f 100644 --- a/03-DESIGN/01-to-be/02-scenario-declaration.md +++ b/03-DESIGN/01-to-be/02-scenario-declaration.md @@ -388,6 +388,115 @@ This is **not** the same as `machines[].inbound`, and conflating them loses a re A mesh node behind a `policy` deny cannot be reached even by a peer that knows exactly where it is — and that is a real topology, not a contrived one. +## Worked example — a whole mesh of the ordinary kind + +The shape research 004 identified: one machine with a routable address, one publicly named but +behind a household connection, one stationary machine on that network, one that roams. Written +out completely, with every field the model has. + +```yaml +scenario: the-ordinary-shape + +segments: + internet: + kind: public + cidr: [203.0.113.0/24, 2001:db8::/32] + mtu: 1500 + + home: # the household network + kind: private + cidr: [192.168.1.0/24, 2001:db8:1::/64] + mtu: 1492 # PPPoE on the uplink; 1500 if the line is not PPPoE + gateway: + to: internet + address: 203.0.113.50 # the address the ISP hands the household + nat: [v4] # v4 translated, v6 routed — the modern default + forwardable: true # the household router is ours to configure + mapping_ttl: 120s + + devices: # optional: a segmented network on the same router + kind: private + cidr: [192.168.30.0/24] + gateway: + to: internet + address: 203.0.113.50 # identical → the SAME gateway machine + nat: [v4] + forwardable: true + mapping_ttl: 120s + + elsewhere: # wherever the roaming machine happens to be + kind: private + cidr: [198.51.100.0/24] + mtu: 1400 + gateway: + to: internet + address: 203.0.113.80 + nat: [v4] + forwardable: false # someone else's network, or carrier-grade NAT + mapping_ttl: 30s + +policy: + - { from: devices, to: home, allow: false } + - { from: home, to: devices, allow: true } + +machines: + anchor: # routable, nothing in front of it + at: { segment: internet, address: [203.0.113.10, 2001:db8::10] } + inbound: allow + + home-server: # publicly named, behind the household connection + at: { segment: home, address: [192.168.1.135, 2001:db8:1::135] } + published: + - { port: 443, on: home } # v4 reaches it only through the forward + inbound: allow # and v6 reaches it directly, so this matters + + workstation: # on the household network, not published + at: { segment: home, address: [192.168.1.250, 2001:db8:1::250] } + inbound: deny + + laptop: # starts at home; moves during the run + at: { segment: home, address: [192.168.1.98, 2001:db8:1::98] } + inbound: deny + +place: + all: [host] + anchor: [substrate] + +snapshot: raised +``` + +### What the ISP modem is doing here + +**Nothing, if it is in bridge mode** — which is the ordinary arrangement when the household has +its own router. A bridged modem is a media converter: it changes the physical medium and leaves +the packets alone, so it creates no IP-level fact and appears nowhere above. + +Were it in router mode it would be a second gateway, `home` would sit behind it rather than +behind `internet` directly, and publishing would need a rule on both — the case the model +cannot yet express. + +### What is deliberately absent + +Nothing here mentions overlay addresses, which node is the hub, who peers with whom, any name, +or any certificate. Research 004 recorded all of those for this topology, and **a scenario must +not state them** ([ADR 0031](../../02-DECISIONS/0031-the-lab-provides-the-underlay.md)): they +are what the mesh does, and a scenario that supplied them would be certifying its own work. + +The absence is the point. Given the declaration above, whether a hub is elected, whether the +NATed machine's endpoint is learned, whether the roaming machine re-forms after moving — all of +it is observed. + +### Running it + +``` +move laptop → { segment: elsewhere, address: [198.51.100.23] } # it leaves the house +move laptop → detached # it sleeps +move laptop → { segment: home, address: [192.168.1.98, 2001:db8:1::98] } +``` + +One identity, four positions, one run. The `mapping_ttl: 30s` on `elsewhere` means a connection +held without refreshing dies while it is out — which is the point of putting a number there. + ## Is this general? — the axes a setup can vary along The question that matters is not *does this cover our mesh*, but **can it express any mesh**.