From dd7dfdd6f75746a82ad8c1c457d7f4099514b3be Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 5 Nov 2026 14:05:54 +0100 Subject: [PATCH] =?UTF-8?q?mesh-connectivity-contracts:=20the=20Connectivi?= =?UTF-8?q?ty=20domain's=20contracts=20module=20moves=20here=20from=20mesh?= =?UTF-8?q?-contracts;=20the-private-network=20defined=20whole,=20no=20cli?= =?UTF-8?q?ent=20(ADR=200636=20=C2=A76;=20issue=201966)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig --- .../go/seats/theprivatenetwork/contract.go | 10 +++ .../go/seats/theprivatenetwork/go.mod | 3 + .../mesh-connectivity-contracts/module.json | 29 ++++++ .../seats/mesh-dns-resolver/seat.json | 9 ++ .../seats/node-hostname/seat.json | 73 +++++++++++++++ .../seats/node-intrusion-prevention/seat.json | 89 +++++++++++++++++++ .../seats/node-packet-filter/seat.json | 62 +++++++++++++ .../seats/node-resolver/seat.json | 77 ++++++++++++++++ .../seats/node-uplink/seat.json | 33 +++++++ .../seats/the-private-network/seat.json | 18 ++++ .../seats/theprivatenetwork/package-lock.json | 12 +++ .../ts/seats/theprivatenetwork/package.json | 13 +++ .../ts/seats/theprivatenetwork/src/index.ts | 9 ++ .../ts/seats/theprivatenetwork/tsconfig.json | 12 +++ 14 files changed, 449 insertions(+) create mode 100644 modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/contract.go create mode 100644 modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/go.mod create mode 100644 modules/mesh-connectivity-contracts/module.json create mode 100644 modules/mesh-connectivity-contracts/seats/mesh-dns-resolver/seat.json create mode 100644 modules/mesh-connectivity-contracts/seats/node-hostname/seat.json create mode 100644 modules/mesh-connectivity-contracts/seats/node-intrusion-prevention/seat.json create mode 100644 modules/mesh-connectivity-contracts/seats/node-packet-filter/seat.json create mode 100644 modules/mesh-connectivity-contracts/seats/node-resolver/seat.json create mode 100644 modules/mesh-connectivity-contracts/seats/node-uplink/seat.json create mode 100644 modules/mesh-connectivity-contracts/seats/the-private-network/seat.json create mode 100644 modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package-lock.json create mode 100644 modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package.json create mode 100644 modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/src/index.ts create mode 100644 modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/tsconfig.json diff --git a/modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/contract.go b/modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/contract.go new file mode 100644 index 0000000..edf8a36 --- /dev/null +++ b/modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/contract.go @@ -0,0 +1,10 @@ +// Code generated by seatgen from the seat definitions; DO NOT EDIT. + +// Package theprivatenetwork is the contract of the seat "the-private-network", defined whole (seats/the-private-network/seat.json): The seat of the private network (ADR 0110): the one network the mesh runs over, which a machine can have only one of; the mesh provides its holder itself and the provision carries no fields. +package theprivatenetwork + +// Seat is the seat's name. +const Seat = "the-private-network" + +// PrivateNetworkForm is the form of the provision private-network. +type PrivateNetworkForm = map[string]any diff --git a/modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/go.mod b/modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/go.mod new file mode 100644 index 0000000..f0aedd2 --- /dev/null +++ b/modules/mesh-connectivity-contracts/go/seats/theprivatenetwork/go.mod @@ -0,0 +1,3 @@ +module git.novox.be/novox/mesh-networking/modules/mesh-connectivity-contracts/go/seats/theprivatenetwork + +go 1.26.0 diff --git a/modules/mesh-connectivity-contracts/module.json b/modules/mesh-connectivity-contracts/module.json new file mode 100644 index 0000000..ceea17e --- /dev/null +++ b/modules/mesh-connectivity-contracts/module.json @@ -0,0 +1,29 @@ +{ + "module": "mesh-connectivity-contracts", + "version": "1", + "build": { + "artifacts": [ + { + "name": "go-theprivatenetwork", + "kind": "package", + "language": "go", + "paths": [ + "go/seats/theprivatenetwork" + ], + "series": "0.1", + "generated-from": "." + }, + { + "name": "ts-theprivatenetwork", + "kind": "package", + "language": "typescript", + "paths": [ + "ts/seats/theprivatenetwork" + ], + "series": "0.1", + "generated-from": "." + } + ] + }, + "resources": [] +} diff --git a/modules/mesh-connectivity-contracts/seats/mesh-dns-resolver/seat.json b/modules/mesh-connectivity-contracts/seats/mesh-dns-resolver/seat.json new file mode 100644 index 0000000..14480ac --- /dev/null +++ b/modules/mesh-connectivity-contracts/seats/mesh-dns-resolver/seat.json @@ -0,0 +1,9 @@ +{ + "format": 1, + "seat": "mesh-dns-resolver", + "scope": "mesh", + "grain": "seat-list", + "decision": "novox/hq ADR 0194, ADR 0223", + "delivers": "wildcard-resolution", + "replicated": true +} diff --git a/modules/mesh-connectivity-contracts/seats/node-hostname/seat.json b/modules/mesh-connectivity-contracts/seats/node-hostname/seat.json new file mode 100644 index 0000000..0f646af --- /dev/null +++ b/modules/mesh-connectivity-contracts/seats/node-hostname/seat.json @@ -0,0 +1,73 @@ +{ + "format": 1, + "seat": "node-hostname", + "scope": "node", + "grain": "seat-list", + "decision": "novox/hq ADR 0199, ADR 0223", + "verbs": [ + { + "name": "entries", + "description": "Every line of this machine's /etc/hosts, each marked whose it is: the operator's, or the block of the module or tool that writes it.", + "replaces": [ + "cat /etc/hosts", + "getent hosts" + ], + "input": { + "properties": {}, + "type": "object" + } + }, + { + "name": "add", + "description": "Add one address and its names to the operator's lines of this machine's /etc/hosts — a name for this machine's own programs, not the mesh's.", + "replaces": [ + "edit /etc/hosts", + "HOSTALIASES" + ], + "input": { + "properties": { + "address": { + "description": "the IPv4 or IPv6 address", + "type": "string" + }, + "names": { + "description": "the names for it, separated by spaces", + "type": "string" + } + }, + "required": [ + "address", + "names" + ], + "type": "object" + } + }, + { + "name": "remove", + "description": "Remove one name, or every line of one address, from the operator's lines of this machine's /etc/hosts. A line a module writes is refused, naming the module.", + "replaces": [ + "sed -i /etc/hosts" + ], + "input": { + "properties": { + "name": { + "description": "a host name, or an address to remove every line of", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + } + ], + "paths": [ + { + "path": "/etc/hosts" + }, + { + "path": "/etc/hostname" + } + ] +} diff --git a/modules/mesh-connectivity-contracts/seats/node-intrusion-prevention/seat.json b/modules/mesh-connectivity-contracts/seats/node-intrusion-prevention/seat.json new file mode 100644 index 0000000..a987a70 --- /dev/null +++ b/modules/mesh-connectivity-contracts/seats/node-intrusion-prevention/seat.json @@ -0,0 +1,89 @@ +{ + "format": 1, + "seat": "node-intrusion-prevention", + "scope": "node", + "grain": "seat-list", + "decision": "novox/hq ADR 0121", + "verbs": [ + { + "name": "status", + "description": "Every jail on this machine with how many it is watching and holding now, and the totals since the jail started; one jail's detail when named.", + "replaces": [ + "fail2ban-client status" + ], + "input": { + "properties": { + "jail": { + "description": "one jail (optional)", + "type": "string" + } + }, + "type": "object" + } + }, + { + "name": "banned", + "description": "Every address banned on this machine right now, with the jail that holds it and when the ban ends.", + "replaces": [ + "fail2ban-client banned" + ], + "input": { + "properties": { + "jail": { + "description": "one jail (optional)", + "type": "string" + } + }, + "type": "object" + } + }, + { + "name": "ban", + "description": "Ban one address in one jail now, for the jail's ban time — an operator's act on the live ban list, which the mesh never writes itself.", + "replaces": [ + "fail2ban-client set banip" + ], + "input": { + "properties": { + "ip": { + "description": "the address", + "type": "string" + }, + "jail": { + "description": "the jail to hold it", + "type": "string" + } + }, + "required": [ + "ip", + "jail" + ], + "type": "object" + } + }, + { + "name": "unban", + "description": "Let one address go, from one jail or from every jail when none is named.", + "replaces": [ + "fail2ban-client unban", + "fail2ban-client set unbanip" + ], + "input": { + "properties": { + "ip": { + "description": "the address", + "type": "string" + }, + "jail": { + "description": "one jail (optional)", + "type": "string" + } + }, + "required": [ + "ip" + ], + "type": "object" + } + } + ] +} diff --git a/modules/mesh-connectivity-contracts/seats/node-packet-filter/seat.json b/modules/mesh-connectivity-contracts/seats/node-packet-filter/seat.json new file mode 100644 index 0000000..fb69e1c --- /dev/null +++ b/modules/mesh-connectivity-contracts/seats/node-packet-filter/seat.json @@ -0,0 +1,62 @@ +{ + "format": 1, + "seat": "node-packet-filter", + "scope": "node", + "grain": "seat-list", + "decision": "novox/hq ADR 0121", + "verbs": [ + { + "name": "rules", + "description": "The packet filter as this machine enforces it now: the nftables ruleset and, where the tool exists, the legacy filter's listings. Narrowed to one table or chain when asked.", + "replaces": [ + "nft list ruleset", + "iptables -L", + "iptables-save" + ], + "input": { + "properties": { + "chain": { + "description": "one chain of that table (optional)", + "type": "string" + }, + "table": { + "description": "one nftables table, as `family name` (optional)", + "type": "string" + } + }, + "type": "object" + } + }, + { + "name": "reload", + "description": "Load the mesh's own filter again from the file the mesh writes, and answer with the mesh's table as loaded.", + "replaces": [ + "nft -f" + ], + "input": { + "properties": {}, + "type": "object" + } + }, + { + "name": "remove", + "description": "Remove one rule set the mesh did not write, named exactly as the host reports it (novox/hq ADR 0168) — `chain X (iptables-legacy)` or `table ip6 filter, chain DOCKER-USER`. Refuses the mesh's tables, the runtime's own chains, a built-in chain and an active found firewall's chains. An operator's act, by name, never a flush.", + "replaces": [ + "nft delete", + "iptables -X" + ], + "input": { + "properties": { + "where": { + "description": "the rule set, as `node show` lists it", + "type": "string" + } + }, + "required": [ + "where" + ], + "type": "object" + } + } + ] +} diff --git a/modules/mesh-connectivity-contracts/seats/node-resolver/seat.json b/modules/mesh-connectivity-contracts/seats/node-resolver/seat.json new file mode 100644 index 0000000..8689bcd --- /dev/null +++ b/modules/mesh-connectivity-contracts/seats/node-resolver/seat.json @@ -0,0 +1,77 @@ +{ + "format": 1, + "seat": "node-resolver", + "scope": "node", + "grain": "seat-list", + "decision": "novox/hq ADR 0247", + "verbs": [ + { + "name": "routes", + "description": "What this machine's own resolver sends where: the mesh's resolvers, which answer every name not routed elsewhere, and each link given servers of its own with the domains routed to them. Also the resolver file's outside writes it kept, newest first: when, who wrote it as far as the file says, whether a module took it, and when the resolver's own file was put back.", + "replaces": [ + "resolvectl status", + "resolvectl dns", + "resolvectl domain" + ], + "input": { + "properties": {}, + "type": "object" + } + }, + { + "name": "route", + "description": "Send these domains, and every name under them, to these servers over this link — and only them: the link is never the machine's default route for names, and the mesh's own domain is refused. Replaces whatever the link was given before. A link that goes away takes its route with it.", + "replaces": [ + "resolvectl dns", + "resolvectl domain", + "resolvectl default-route" + ], + "input": { + "properties": { + "domains": { + "description": "the domains to route there, separated by spaces or commas", + "type": "string" + }, + "link": { + "description": "the network link the servers are reached over, by name (a VPN's tunnel interface)", + "type": "string" + }, + "servers": { + "description": "the servers' addresses, separated by spaces or commas", + "type": "string" + } + }, + "required": [ + "link", + "domains", + "servers" + ], + "type": "object" + } + }, + { + "name": "unroute", + "description": "Take one link's route away: its domains go back to the mesh's resolvers. Nothing changes when the link has none.", + "replaces": [ + "resolvectl revert" + ], + "input": { + "properties": { + "link": { + "description": "the network link, by name", + "type": "string" + } + }, + "required": [ + "link" + ], + "type": "object" + } + } + ], + "paths": [ + { + "path": "/etc/resolv.conf" + } + ] +} diff --git a/modules/mesh-connectivity-contracts/seats/node-uplink/seat.json b/modules/mesh-connectivity-contracts/seats/node-uplink/seat.json new file mode 100644 index 0000000..0ecfbf1 --- /dev/null +++ b/modules/mesh-connectivity-contracts/seats/node-uplink/seat.json @@ -0,0 +1,33 @@ +{ + "format": 1, + "seat": "node-uplink", + "scope": "node", + "grain": "seat-list", + "decision": "novox/hq ADR 0117", + "verbs": [ + { + "name": "resolvers", + "description": "The machine's resolver file as it is now: the resolvers, search domains and options it lists, whether it is the file the mesh declares, and when it is not, who wrote it as far as the machine shows — its header, a backup a VPN client left beside it, a link in its place, a known writer running.", + "optional": true, + "input": { + "properties": {}, + "type": "object" + } + }, + { + "name": "links", + "description": "Every network link on the machine: its state, its addresses, whether the default route leaves through it, and the resolvers and search domains the network manager knows for it — a VPN's tunnel included.", + "optional": true, + "input": { + "properties": {}, + "type": "object" + } + } + ], + "paths": [ + { + "path": "/etc/resolv.conf", + "steps-back-for": "node-resolver" + } + ] +} diff --git a/modules/mesh-connectivity-contracts/seats/the-private-network/seat.json b/modules/mesh-connectivity-contracts/seats/the-private-network/seat.json new file mode 100644 index 0000000..2646620 --- /dev/null +++ b/modules/mesh-connectivity-contracts/seats/the-private-network/seat.json @@ -0,0 +1,18 @@ +{ + "format": 1, + "seat": "the-private-network", + "scope": "node", + "grain": "whole", + "decision": "novox/hq ADR 0110, ADR 0634, ADR 0635", + "description": "The seat of the private network (ADR 0110): the one network the mesh runs over, which a machine can have only one of; the mesh provides its holder itself and the provision carries no fields.", + "verbs": [], + "provisions": [ + { + "name": "private-network", + "form": { + "type": "object", + "description": "the provision has no fields: it is the machine's reach to the others" + } + } + ] +} diff --git a/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package-lock.json b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package-lock.json new file mode 100644 index 0000000..c8b64fa --- /dev/null +++ b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package-lock.json @@ -0,0 +1,12 @@ +{ + "lockfileVersion": 3, + "name": "@novox/mesh-connectivity-contracts-the-private-network", + "packages": { + "": { + "name": "@novox/mesh-connectivity-contracts-the-private-network", + "version": "0.1.0" + } + }, + "requires": true, + "version": "0.1.0" +} diff --git a/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package.json b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package.json new file mode 100644 index 0000000..2425c77 --- /dev/null +++ b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/package.json @@ -0,0 +1,13 @@ +{ + "description": "The contract of the seat the-private-network, generated from its definition.", + "exports": { + ".": "./src/index.ts" + }, + "files": [ + "src" + ], + "name": "@novox/mesh-connectivity-contracts-the-private-network", + "type": "module", + "types": "./src/index.ts", + "version": "0.1.0" +} diff --git a/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/src/index.ts b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/src/index.ts new file mode 100644 index 0000000..d04f2cd --- /dev/null +++ b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/src/index.ts @@ -0,0 +1,9 @@ +// Code generated by seatgen from the seat definitions; DO NOT EDIT. + +// The contract of the seat "the-private-network", defined whole (seats/the-private-network/seat.json): The seat of the private network (ADR 0110): the one network the mesh runs over, which a machine can have only one of; the mesh provides its holder itself and the provision carries no fields. + +export const seat = "the-private-network"; + +/** is the form of the provision private-network. */ +export type PrivateNetworkForm = Record; + diff --git a/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/tsconfig.json b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/tsconfig.json new file mode 100644 index 0000000..60274c6 --- /dev/null +++ b/modules/mesh-connectivity-contracts/ts/seats/theprivatenetwork/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*.ts"] +}