A secret that will never be readable stops calling itself a race (hq issue 225)

The harness says 'secret not readable yet' when it cannot open a consumer's
sealed credential, which is true and ordinary on the first pass. It said it
4330 times in three hours on the control machine while two consumers were
never provisioned, because a permission the host will never grant reads
exactly like a file that has not arrived.

After about a minute it says so plainly instead, once and then rarely, and
names what to look at: who owns the file and who this process runs as. The
ownership itself is the controller's to fix.

0.1.9.
This commit is contained in:
2026-10-04 12:13:54 +02:00
parent 41ec9806db
commit c77fc500f5
4 changed files with 73 additions and 4 deletions
+37
View File
@@ -123,6 +123,43 @@ test("provisioner hands the adapter what the mesh derived, and still has it at w
stop();
});
test("provisioner stops calling an unreadable secret a race, and says what to look at", async () => {
// novox/hq issue 225. A permission the host will never grant reads exactly like a file that has
// not arrived yet, and three hours of "not readable yet" is how a provider that served nobody
// looked healthy. After a while the wording has to change, because the word "yet" is the fault.
const dir = await mkdtemp(join(tmpdir(), "prov-unreadable-"));
const receives = join(dir, "db.json");
await writeFile(
receives,
JSON.stringify({
contributions: 1, requirement: "db",
given: [{ from: "photos", node: "anchor", as: "mesh_anchor_photos",
secret: join(dir, "never-written.secret"), values: {} }],
}),
);
const said: string[] = [];
const wasError = console.error;
console.error = (line: unknown) => { said.push(String(line)); };
let stop: (() => void) | undefined;
try {
stop = runProvisioner("db", { async create() {}, async remove() {} }, { receives, everyMs: 5 });
await waitFor(() => said.some((l) => l.includes("CANNOT READ")), 3000);
} finally {
stop?.();
console.error = wasError;
}
const patient = said.filter((l) => l.includes("not readable yet"));
const loud = said.filter((l) => l.includes("CANNOT READ"));
assert.ok(patient.length > 0, "it never gave the host a chance to write the file");
assert.ok(patient.length <= 12, `it called a permanent refusal a race ${patient.length} times`);
assert.ok(loud.length > 0, "it never stopped calling it a race");
// And the loud one says where to look, because the answer is ownership and not the mesh.
assert.ok(loud[0].includes("who owns the file"), `the loud line does not say what to check: ${loud[0]}`);
assert.ok(loud[0].includes("issue 225"), "the loud line does not name the record");
});
test("provisioner applies again what the backend no longer holds, and trusts memory without holds", async () => {
const dir = await mkdtemp(join(tmpdir(), "prov-holds-"));
await writeFile(join(dir, "webapp.secret"), "minted-pw\n");