From 475fd9a088a89f4a92ce170f88f8a18cfc317f1f Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 14 Sep 2026 22:52:26 +0200 Subject: [PATCH] Register the firewall before assigning it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'no module of that name: firewall'. The networking family is computed by the control plane, so the mesh knows those exist without anyone saying so; the firewall is an ordinary catalogue module and has to be added like any other. That is a second way for a module to be absent, and a less obvious one than being present and placed nowhere — the mesh does not hold it at all, so nothing can even report it unassigned. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- one-node-mesh-report.json | 55 +++++++++++++++----------- test/integration/one-node-mesh.test.ts | 8 ++++ 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/one-node-mesh-report.json b/one-node-mesh-report.json index 9136f06..9ac706f 100644 --- a/one-node-mesh-report.json +++ b/one-node-mesh-report.json @@ -1,13 +1,13 @@ { "scenario": "one-node-mesh", - "established": 16, - "of": 20, + "established": 12, + "of": 21, "steps": [ { "code": "R1", "title": "a bare machine becomes a mesh of one, raised by the installer", "status": "pass", - "seconds": 140, + "seconds": 135, "why": "" }, { @@ -56,21 +56,21 @@ "code": "P1", "title": "the mesh builds the shared base from source", "status": "pass", - "seconds": 74, + "seconds": 87, "why": "" }, { "code": "P2", "title": "the mesh builds and runs a store of its own", "status": "pass", - "seconds": 53, + "seconds": 41, "why": "" }, { "code": "P3", "title": "the mesh builds and runs its own catalogue", "status": "pass", - "seconds": 25, + "seconds": 37, "why": "" }, { @@ -84,50 +84,57 @@ "code": "N1", "title": "the mesh puts itself on a private network, and its machine has a name", "status": "pass", - "seconds": 6, + "seconds": 7, "why": "" }, + { + "code": "N2", + "title": "the machine has a packet filter, loaded from what modules declared", + "status": "fail", + "seconds": 0, + "why": "anchor: docker exec mesh-control /mesh-control assign anchor firewall\n\nmesh-control: no module of that name: firewall\n" + }, { "code": "U1", "title": "the mesh builds a module standing on that base", - "status": "pass", - "seconds": 14, - "why": "" + "status": "skip", + "seconds": 0, + "why": "not attempted — N2 (the machine has a packet filter, loaded from what modules declared) did not succeed" }, { "code": "U2", "title": "the mesh runs a broker for that module to talk to", - "status": "pass", - "seconds": 20, - "why": "" + "status": "skip", + "seconds": 0, + "why": "not attempted — U1 (the mesh builds a module standing on that base) did not succeed" }, { "code": "U3", "title": "the anchor runs the module the mesh built", - "status": "pass", - "seconds": 6, - "why": "" + "status": "skip", + "seconds": 0, + "why": "not attempted — U2 (the mesh runs a broker for that module to talk to) did not succeed" }, { "code": "V1", "title": "the control plane can describe the mesh, and what it says is true", - "status": "pass", - "seconds": 1, - "why": "" + "status": "skip", + "seconds": 0, + "why": "not attempted — U3 (the anchor runs the module the mesh built) did not succeed" }, { "code": "V2", "title": "the catalogue holds every module this mesh built", - "status": "fail", - "seconds": 1, - "why": "the catalogue does not hold mesh-tools, postgres — the mesh built them and its own record has no trace of it (novox/hq issue 050):\n{\"modules\":[{\"module\":\"amqp-ping\",\"commit\":\"e0c92195d4240841bfcf4b4a9ef869d5afeca331\",\"repository\":\"https://git.novox.be/novox/mesh-catalog.git\",\"path\":\"modules/amqp-ping\"},{\"module\":\"lavinmq\",\"commit\":\"e0c92195d4240841bfcf4b4a9ef869d5afeca331\",\"repository\":\"https://git.novox.be/novox/mesh-catalog.git\",\"path\":\"modules/lavinmq\"},{\"module\":\"mesh-control\",\"commit\":\"5062c36fc9efe159aa9706c0ca2c873351ef1ce0\",\"repository\":\"https://git.novox.be/novox/mesh-control.git\",\"path\":\"\"}]}\n\n+ actual - expected\n\n+ [\n+ 'mesh-tools',\n+ 'postgres'\n+ ]\n- []\n" + "status": "skip", + "seconds": 0, + "why": "not attempted — V1 (the control plane can describe the mesh, and what it says is true) did not succeed" }, { "code": "V3", "title": "the machine's networking is what the modules asked for", - "status": "fail", + "status": "skip", "seconds": 0, - "why": "the mesh's own firewall table is not there:\nError: No such file or directory\nlist table inet mesh\n ^^^^\n" + "why": "not attempted — V1 (the control plane can describe the mesh, and what it says is true) did not succeed" }, { "code": "E1", diff --git a/test/integration/one-node-mesh.test.ts b/test/integration/one-node-mesh.test.ts index 11d800e..c7c09bd 100644 --- a/test/integration/one-node-mesh.test.ts +++ b/test/integration/one-node-mesh.test.ts @@ -641,6 +641,14 @@ before(async () => { // and the second is the more alarming of the two — every rule the mesh generates from module // declarations had never been applied to any machine in this test. await step("N2", FILTERED, NETWORKED, async () => { + // **Registered first: the mesh had never heard of it.** The networking family is computed by + // the control plane, so the mesh knows those modules exist without anyone saying so. The + // firewall is an ordinary catalogue module and needs adding like any other — "no module of + // that name: firewall" — which is a second way for a module to be absent, and less obvious + // than being present and placed nowhere. + // + // No build: its resources are a package and a service, so there is nothing to compile. + await registerModule(FILTER_MODULE, resolve(catalogDir, FILTER_MODULE, "module.json")); await mesh(`assign ${CONTROL} ${FILTER_MODULE}`); await mesh(`push ${CONTROL}`, 600_000); const deadline = Date.now() + 180_000;