Beds for the seed file and for the foundation's filter

The vault bed grows into a create-once file and pushes again; the genesis bed
probes the machine from the workstation for the whole install and asserts the
store's port never answers while the bus's does.
This commit is contained in:
2026-09-21 12:11:52 +02:00
parent 7e2e97f056
commit 599d41eb42
2 changed files with 70 additions and 0 deletions
+40
View File
@@ -40,6 +40,7 @@ import { test, before, after } from "node:test";
import assert from "node:assert/strict";
import { existsSync, readFileSync, writeFileSync, appendFileSync } from "node:fs";
import { execFileSync } from "node:child_process";
import net from "node:net";
import { resolve } from "node:path";
import { loadScenario } from "../../src/declaration/parse.ts";
import { raise } from "../../src/lifecycle/raise.ts";
@@ -247,6 +248,31 @@ async function mesh(command: string, timeoutMs?: number): Promise<string> {
}
}
/** The machine's address on the lab's uplink bridge — the one the workstation can dial. */
async function uplinkAddressOf(machine: string): Promise<string> {
const name = await instanceNameOf(instanceId, machine);
const listed = (await incus(["list", name, "--format", "csv", "-c", "4"], 30_000)).stdout;
const addresses = listed.split(/[,\s]+/).map((a: string) => a.trim()).filter((a: string) => /^10\./.test(a));
assert.ok(addresses.length > 0, `no uplink address for ${machine} in:\n${listed}`);
return addresses[0] as string;
}
/** Try to open a TCP connection every two seconds to each port, and remember whether any attempt ever succeeded. */
function probeFromOutside(address: string, ports: number[]): { stop(): void; seen(): Map<number, boolean> } {
const seen = new Map<number, boolean>(ports.map((p) => [p, false]));
const attempt = () => {
for (const port of ports) {
const socket = net.connect({ host: address, port, timeout: 1000 });
socket.once("connect", () => { seen.set(port, true); socket.destroy(); });
socket.once("timeout", () => socket.destroy());
socket.once("error", () => socket.destroy());
}
};
attempt();
const timer = setInterval(attempt, 2000);
return { stop: () => clearInterval(timer), seen: () => seen };
}
/** Until the anchor reports the last declaration genesis pushed as applied and current. */
async function settledAfterGenesis(withinMs = 300_000): Promise<void> {
const deadline = Date.now() + withinMs;
@@ -508,6 +534,11 @@ before(async () => {
// nothing held: no image is pre-resolved, because none is here to resolve to.
await step("R1", GENESIS, null, async () => {
try {
// Probed from the workstation for the whole install (novox/hq ADR 0088, issue 054): the
// store's client port must never answer from outside the machine, while the bus's must
// come to — which is also what proves the probe reaches the machine at all.
const probe = probeFromOutside(await uplinkAddressOf(CONTROL), [5432, 5671]);
try {
raised = await genesis({
instanceId,
node: CONTROL,
@@ -538,6 +569,15 @@ before(async () => {
...(binary ? { hostBinary: binary } : {}),
log: (m) => console.log(m),
});
} finally {
probe.stop();
}
const seen = probe.seen();
assert.equal(seen.get(5432), false,
"the store's port answered from outside the machine during the install — the base filter did not hold (issue 054)");
assert.equal(seen.get(5671), true,
"the bus never answered from outside during the install, so the probe proves nothing — is the uplink address right?");
raised.report.push(` filtered 5432 never answered from outside during the install; 5671 did`);
} catch (err) {
throw new Error(`the installer never ran: ${(err as Error).message}`);
}