The filter constrains what arrives from outside, and names no network

The forward chain blocked everything passing through the machine and then allowed
the machine's own containers back by naming their address ranges: 172.16.0.0/12 and
192.168.128.0/17 fixed here, the rest recorded per machine by 0043. Every way of
keeping that list correct fails — a constant describes one machine, a recorded range
goes stale in silence and cannot tell a network the mesh made from one a predecessor
left behind, and generating it from the modules would put half the rule set on the
machine.

The mesh has no position on a container reaching outward: that is not a port opened
to anybody. So both chains are written around the links traffic arrives on. What did
not arrive from outside is accepted in one line; what did meets the declared rules.
The tunnel is named beside the outward links rather than treated as inside, or a port
nothing declares would be reachable from every machine in the mesh.

A machine that has not reported an outward link is sent no filter and keeps the one
it has, refused where a person reads it rather than as a rule set that will not load.

Removes the two constants, `node networks`, and the column behind it. novox/hq ADR
0140, superseding 0137 and 0139.
This commit is contained in:
2026-09-29 01:01:29 +02:00
parent ed5d467d90
commit fe5988c536
15 changed files with 347 additions and 332 deletions
+11 -67
View File
@@ -21,8 +21,7 @@ import (
func nodeCommand(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("node add <name>, node list, node show <name>, " + publicDomainUsage +
", or " + networksUsage)
return errors.New("node add <name>, node list, node show <name>, or " + publicDomainUsage)
}
open, err := openStores(ctx)
if err != nil {
@@ -68,10 +67,16 @@ func nodeCommand(ctx context.Context, args []string) error {
return publicDomain(ctx, inv, args[1:])
case "networks":
// The networks this machine routes for what it hosts (novox/hq ADR 0137): what the derived
// filter must keep forwarding, beyond the container runtime's own default pools which it
// allows without being told. Reports with no argument, for the same reason the domain does.
return nodeNetworks(ctx, inv, args[1:])
// Removed by novox/hq ADR 0140, which superseded the record that added it. The filter no
// longer names any network: it constrains what arrives from outside the machine and says
// nothing about what did not, so there is no list to keep. Answered rather than met with
// "unknown command", because this was the documented way to stop a flip cutting a machine's
// containers off and somebody will reasonably still type it.
return errors.New("`node networks` is gone (novox/hq ADR 0140). The filter constrains what " +
"arrives from outside this machine and says nothing about traffic that did not, so no " +
"network is named anywhere and nothing needs to be said to keep a machine's own " +
"containers reaching outward. The machine reports which of its links face outside; see " +
"`node show <name>`")
case "account":
// The operator's login on this machine (novox/hq to-be 29): what a home-scoped file is
@@ -151,67 +156,6 @@ func nodeAccount(ctx context.Context, inv *inventory.Inventory, positionals []st
return nil
}
const networksUsage = "node networks <name> — what it routes now; " +
"<name> <cidr>... to set them; <name> --clear to route only the container runtime's own"
// nodeNetworks reads, sets or clears the networks a machine routes for what it hosts.
//
// The same three forms as the domain above, and the read-shaped one reports rather than clearing,
// for the same reason: this list is what keeps a machine's guests reaching anything, and losing it
// by asking a question is not a mistake anybody can see afterwards.
func nodeNetworks(ctx context.Context, inv *inventory.Inventory, args []string) error {
set := flag.NewFlagSet("node networks", flag.ContinueOnError)
clear := set.Bool("clear", false,
"route only the container runtime's own default pools, as a machine that has said nothing does")
positionals, err := parseAround(set, args)
if err != nil {
return err
}
if len(positionals) == 0 {
return errors.New(networksUsage)
}
node := positionals[0]
switch {
case *clear && len(positionals) > 1:
return fmt.Errorf("give %s networks or --clear, not both: %q and --clear say opposite "+
"things and the mesh will not choose between them", node, strings.Join(positionals[1:], " "))
case *clear:
if err := inv.SetRoutedNetworks(ctx, node, nil); err != nil {
return err
}
fmt.Printf("%s routes only the container runtime's own default pools\n", node)
fmt.Printf(" run `push %s` to send its filter\n", node)
return nil
case len(positionals) > 1:
if err := inv.SetRoutedNetworks(ctx, node, positionals[1:]); err != nil {
return err
}
fmt.Printf("%s routes %s\n", node, strings.Join(positionals[1:], ", "))
fmt.Printf(" its filter forwards them, and their guests keep address and name service\n")
fmt.Printf(" run `push %s` to send it\n", node)
return nil
default:
if _, err := inv.NodeByName(ctx, node); err != nil {
return err
}
networks, err := inv.RoutedNetworksOf(ctx, node)
if err != nil {
return err
}
if len(networks) == 0 {
fmt.Printf("%s routes only the container runtime's own default pools\n", node)
fmt.Printf(" `node networks %s <cidr>...` if its guests live elsewhere\n", node)
return nil
}
fmt.Printf("%s routes %s\n", node, strings.Join(networks, ", "))
return nil
}
}
const publicDomainUsage = "node public-domain <name> — what it is now; " +
"<name> <domain> to set it; <name> --clear to take it away"