feat: preserve evidence in workspace artifacts

This commit is contained in:
2026-08-09 20:03:28 +02:00
parent 64b778ade9
commit 212c973e3b
6 changed files with 656 additions and 7 deletions
+97 -2
View File
@@ -1,7 +1,7 @@
import { execFile } from "node:child_process";
import { createHash } from "node:crypto";
import {
chmodSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, symlinkSync, writeFileSync,
chmodSync, existsSync, mkdtempSync, mkdirSync, readdirSync, readFileSync, rmSync, symlinkSync, writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -9,7 +9,9 @@ import { promisify } from "node:util";
import { afterEach, expect, test } from "vitest";
import { WorkspaceRepositoryLock } from "../src/workspaces/git-repository.js";
import { WorkspaceRegistry } from "../src/workspaces/registry.js";
import { parseWorkspaceYaml, type CanonicalWorkspace } from "../src/workspaces/schema.js";
import {
parseWorkspaceYaml, renderWorkspaceDocs, serializeWorkspaceYaml, type CanonicalWorkspace,
} from "../src/workspaces/schema.js";
import type { WorkspaceRegistryConfig } from "../src/workspaces/types.js";
const validYaml = `workspace:
@@ -988,3 +990,96 @@ test("rejects a corrupt fallback snapshot instead of returning degraded active s
await expect(registry.pull()).rejects.toMatchObject({ code: "workspace_invalid" });
});
test("snapshots canonical Evidence artifacts at the active commit without copying Evidence bytes", async () => {
const remote = await fixture(withFilesystemEvidence(validYaml));
const registryRoot = join(remote.root, "registry");
const registry = new WorkspaceRegistry(config(registryRoot, remote.remote));
const status = await registry.bootstrap();
const active = await registry.read("psd-clinical");
const snapshotDirectory = join(registryRoot, "snapshots", status.head!);
const descriptor = active.workspace as CanonicalWorkspace;
const docs = renderWorkspaceDocs(descriptor);
const expectedFiles: Record<string, string> = {
"psd-clinical.yaml": serializeWorkspaceYaml(descriptor),
"psd-clinical.env.example": docs.envExample,
"psd-clinical.md": docs.markdown,
};
const manifest = JSON.parse(readFileSync(join(snapshotDirectory, "snapshot.json"), "utf8"));
expect(status.head).toBe(remote.initialCommit);
const committedDescriptor = parseWorkspaceYaml(await gitOutput(remote.source, [
"show", `${remote.initialCommit}:workspaces/psd-clinical.yaml`,
])) as CanonicalWorkspace;
expect(expectedFiles["psd-clinical.yaml"]).toBe(serializeWorkspaceYaml(committedDescriptor));
expect(readdirSync(snapshotDirectory).sort()).toEqual([
"psd-clinical.env.example", "psd-clinical.md", "psd-clinical.yaml", "snapshot.json",
]);
expect(manifest.head).toBe(remote.initialCommit);
expect(manifest.revisions[0]).toMatchObject({
id: "psd-clinical", commit: remote.initialCommit, blob: active.revision.blob,
});
expect(Object.keys(manifest.files).sort()).toEqual(Object.keys(expectedFiles).sort());
for (const [name, contents] of Object.entries(expectedFiles)) {
expect(readFileSync(join(snapshotDirectory, name), "utf8")).toBe(contents);
expect(manifest.files[name]).toBe(createHash("sha256").update(contents).digest("hex"));
}
expect(JSON.stringify(manifest)).not.toContain("workspace-content/");
expect(readdirSync(snapshotDirectory).some((name) => name === "workspace-content")).toBe(false);
expect(readFileSync(join(remote.source, "workspace-content/psd-clinical/evidence/guide.md"), "utf8"))
.toBe("guide v1\n");
});
test("never copies an installation secret canary into Git, generated artifacts, metadata, or errors", async () => {
const remote = await fixture(validYaml.concat(`evidence:
source:
type: http
uris: [https://evidence.example.test/guide.md]
authentication: signed_urls_file
`));
const canary = "CANARY-EVIDENCE-SECRET-ONLY-IN-FIXTURE";
const secretDirectory = join(remote.root, "fixture-secrets");
mkdirSync(secretDirectory);
const secretFile = join(secretDirectory, "signed-urls");
writeFileSync(secretFile, canary);
const registryRoot = join(remote.root, "registry");
const registry = new WorkspaceRegistry(config(registryRoot, remote.remote, {
secretRoots: [secretDirectory],
}));
const previous = process.env.THT_WS_PSD_CLINICAL_EVIDENCE_SIGNED_URLS_FILE;
process.env.THT_WS_PSD_CLINICAL_EVIDENCE_SIGNED_URLS_FILE = secretFile;
try {
const status = await registry.bootstrap();
const snapshotDirectory = join(registryRoot, "snapshots", status.head!);
let gitBlobText = "";
try {
gitBlobText = (await runFile(
"git", ["grep", "-I", "-h", "-e", canary, "HEAD", "--", "."], { cwd: remote.source },
)).stdout;
} catch (error) {
if (!error || typeof error !== "object" || !("code" in error) || error.code !== 1) throw error;
gitBlobText = "stdout" in error ? String(error.stdout ?? "") : "";
}
expect(gitBlobText).toBe("");
for (const name of readdirSync(snapshotDirectory)) {
expect(readFileSync(join(snapshotDirectory, name), "utf8")).not.toContain(canary);
}
let thrown: unknown;
try {
await registry.publish({
action: "create",
workspace: filesystemWorkspace("missing-secret-canary-tree"),
baseCommit: status.head!,
});
} catch (error) {
thrown = error;
}
expect(thrown).toMatchObject({ code: "workspace_invalid" });
expect(String(thrown)).not.toContain(canary);
} finally {
if (previous === undefined) delete process.env.THT_WS_PSD_CLINICAL_EVIDENCE_SIGNED_URLS_FILE;
else process.env.THT_WS_PSD_CLINICAL_EVIDENCE_SIGNED_URLS_FILE = previous;
}
});