diff --git a/test/integration/mesh.test.ts b/test/integration/mesh.test.ts index c78b762..498d450 100644 --- a/test/integration/mesh.test.ts +++ b/test/integration/mesh.test.ts @@ -326,7 +326,8 @@ test("a credential reaches both ends and the mesh holds neither", { skip, timeou // real program takes a credential: a sealed file is a password alone, and almost nothing reads // one. The mesh cannot compose the document — it discarded the value — so the module supplies it // with `${secret:...}` in it and the host, the only thing that sees both halves, fills it in. - await must("anchor", `printf %s '{"module":"meshboard","version":"1",` + + // A slug, so its identity on a backend stays within an S3 access key's 20 characters (ADR 0049). + await must("anchor", `printf %s '{"module":"meshboard","version":"1","slug":"board",` + `"requires":["postgres-database"],"contributes":{"postgres-database":{"name":"meshboard"}},` + `"binds":{"postgres-database":"/etc/meshboard/database.json"},` + `"secrets":{"postgres-database":"/etc/meshboard/database.password"},` + @@ -814,117 +815,11 @@ test("a machine filters exactly what its modules declared, and nothing else", { "the port stayed open after the module that wanted it was removed"); }); -test("the builder is a module the mesh assigns, with a credential the mesh delivered", { - skip: skip || (!builder ? "set MESH_LAB_BUILDER to a built mesh-builder" : false), - timeout: 900_000, -}, async () => { - // Until this, the builder was a program somebody started on a machine with whatever credential - // they had to hand — in practice the broker's administrative one. A program documented as - // holding its own credential and given somebody else's is worse than one with no story at all. - // - // So: the mesh issues a scoped account, seals it to the machine, and delivers it with the - // declaration. Nobody types it and the mesh cannot read it back. - await must("anchor", `mkdir -p /root/builder && printf %s '{"module":"self-builder","version":"1",` + - `"requires":["artifact-store"],"capabilities":["container-runtime"],` + - `"claims":[{"name":"the-build-machine","scope":"node"}],` + - `"binds":{"artifact-store":"/var/lib/mesh/builder/artifact-store.json"},` + - `"own-secrets":{"broker":"/var/lib/mesh/builder/broker"},` + - `"build":{"artifacts":[{"name":"builder","kind":"upstream",` + - `"from":"${pinned("mesh-builder")}"}]},` + - `"resources":[` + - `{"id":"state","type":"directory","path":"/var/lib/mesh/builder","mode":"0700"},` + - `{"id":"workspace","type":"directory","path":"/var/lib/mesh/builder/workspace","mode":"0700"},` + - `{"id":"run","type":"container","name":"mesh-builder","artifact":"builder",` + - `"network":"host",` + - `"volumes":["/var/lib/mesh/builder:/var/lib/mesh/builder",` + - `"/var/run/docker.sock:/var/run/docker.sock"],` + - `"env":{"MESH_BROKER_FILE":"/var/lib/mesh/builder/broker",` + - `"MESH_BINDING":"/var/lib/mesh/builder/artifact-store.json",` + - `"MESH_WORKSPACE":"/var/lib/mesh/builder/workspace"}}]}' > /root/builder/module.json`); - await must("anchor", `cd /root/builder && git init -q . && git add -A && ` + - `git -c user.email=lab -c user.name=lab commit -qm builder`); - - // The builder's own image is built by the builder that is already running — the same - // chicken-and-egg as the registry, resolved the same way. The one started by hand does this - // last piece of work and is then replaced by the module it just built. - await mesh("build /root/builder --wait 300s", 420_000); - - // The mesh makes the account and seals the URL to this machine. Nothing is printed that would - // work if it were pasted somewhere else. - const issued = await mesh("builder issue lab-builder --node anchor"); - assert.match(issued, /sealed to anchor/, issued); - assert.doesNotMatch(issued, /amqps:\/\/lab-builder:/, - "the credential was printed, so the one copy that matters is on a terminal"); - - // Now the hand-started one goes, or two builders race for the same queue and whichever answers - // proves nothing. By process name: `pkill -f` matches the shell running it too, which kills the - // connection carrying the command and hangs the caller waiting for a reply that will never - // come. Cost an hour once, in this file. - await on("anchor", `pkill -x mesh-builder`); - await new Promise((r) => setTimeout(r, 2000)); - assert.ok(!(await on("anchor", `pgrep -x mesh-builder`)).ok, - "the hand-started builder is still running, so this would test that one"); - - await mesh("assign anchor self-builder"); - await mesh("push anchor"); - await new Promise((r) => setTimeout(r, 20_000)); - - const running = await must("anchor", `docker ps --format '{{.Names}}'`); - assert.match(running, /mesh-builder/, - `the builder was assigned and is not running:\n${running}\n` + - `${(await on("anchor", `tail -30 /var/log/mesh-host.log`)).out}`); - - // Running is not connected. A builder that cannot reach the broker sits there, and every - // outward sign — the container is up, the credential is on disk — says it is working. - await new Promise((r) => setTimeout(r, 5000)); - const said = await on("anchor", `docker logs mesh-builder 2>&1 | tail -20`); - assert.doesNotMatch(said.out, /cannot reach the broker/, - `the builder is running and cannot reach the broker:\n${said.out}`); - - // The credential arrived, is readable only by the machine, and is the scoped account rather - // than the broker's own. - assert.match(await must("anchor", `stat -c %a /var/lib/mesh/builder/broker`), /^600/); - const credential = await must("anchor", `cat /var/lib/mesh/builder/broker`); - assert.match(credential, /"url":"amqps:\/\/lab-builder:/, - "the builder is using an account that is not its own"); - assert.doesNotMatch(credential, /guest:guest/, "the builder holds the broker's own account"); - // And what to check the broker against. A mesh's broker presents a certificate of the mesh's - // own, so a URL alone reaches only a broker some public authority vouches for — which is no - // mesh broker at all, and fails at TLS with an error about an unknown authority. - assert.match(credential, /"fingerprint":"(sha256:)?[0-9a-f]{64}"/, - `the builder was given nothing to verify the broker with:\n${credential}`); - - // And it works: the mesh asks this builder to build something, and it does. Answering is the - // only proof that the delivered credential authenticates — a container that is up with a - // credential it cannot use looks identical from outside. - // Somewhere the builder can actually see. A builder that is a module runs in a container, so - // the machine's filesystem is not its own — a path like /root only works for a builder somebody - // started on the host, which is what the first build above used. In a real mesh a module is - // cloned from the forge over a URL; here it goes in the directory the module already mounts, - // which is the same fact wearing different clothes. - const repo = "/var/lib/mesh/builder/repositories/built"; - await must("anchor", `mkdir -p ${repo} && printf %s '{"module":"built","version":"1",` + - `"resources":[{"id":"marker","type":"file","path":"/etc/built","content":"yes","mode":"0644"}]}' ` + - `> ${repo}/module.json`); - await must("anchor", `cd ${repo} && git init -q . && git add -A && ` + - `git -c user.email=lab -c user.name=lab commit -qm built`); - try { - await mesh(`build ${repo} --wait 300s`, 420_000); - } catch (why) { - // The builder's own account of itself. Without it the failure is "nothing consumed the - // queue", which names no cause and is the same sentence whether the credential was refused, - // the queue was never declared, or the process died three seconds in. - const said = (await on("anchor", `docker logs mesh-builder 2>&1 | tail -40`)).out; - throw new Error(`${(why as Error).message}\n\nwhat the builder said:\n${said}`); - } - - // Naming the module, and not merely containing its name: `builds` says "nothing has been built - // yet" when there is nothing, and that sentence contains the word this was matching on. - const recorded = await mesh("builds built"); - assert.doesNotMatch(recorded, /nothing has been built/, - `the build was accepted and no build was recorded against the module:\n${recorded}`); - assert.match(recorded, /built/, recorded); -}); +// The builder as a module the mesh assigns, with a credential the mesh delivered, is what genesis +// proves now (genesis-single installs the catalogue's builder through the installer, novox/hq ADR +// 0069). The test that lived here declared the builder's image as an upstream artifact by the bare +// image ID the lab holds, which is not a reference a registry copy can fetch (ADR 0096); retired +// 2026-09-21 rather than rewritten into a second genesis. test("rotating a credential moves both ends, and the old one stops working", { skip, timeout: 900_000,