fix(environment): report changed export inputs as tagged failures

This commit is contained in:
gensokyo-dev committed 2026-10-19 19:55:48 +00:00
1 parent 8505193343
commit 35eec3f20c
2 files changed
+51

No files matched your search

@@ -12,13 +12,16 @@ import {
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";
import { PACKAGE_METADATA } from "../../generatedPackageMetadata.js";
import { RegularFileChangedError } from "../../filesystem/RegularFile.js";
import { nativeJsonParseRequiredBytes } from "../JsonInputFile.js";
import * as regularFileRead from "../RegularFileRead.js";
import {
exportEnvironmentBundle,
readEnvironmentExportInputs,
} from "./environmentExport.js";
vi.mock("node:v8", { spy: true });
vi.mock("../RegularFileRead.js", { spy: true });
const listFiles = async (root: string): Promise<string[]> =>
(await readdir(root, { recursive: true, withFileTypes: true }))
@@ -44,6 +47,41 @@ const prepare = async (prefix: string) => {
};
describe("readEnvironmentExportInputs", () => {
it.each(["manifest", "evidence"] as const)(
"returns a tagged input error when the %s snapshot changes",
async (role) => {
const root = await createTestTempDirectory(
"rea-environment-input-changed-",
);
const files = await writeEnvironmentServeFiles(root);
const changedPath =
role === "manifest" ? files.manifestPath : files.capturePath;
const actual = await vi.importActual<typeof regularFileRead>(
"../RegularFileRead.js",
);
const reader = vi.mocked(regularFileRead.readRegularFile);
reader.mockImplementation(async (path, options) => {
if (path === changedPath) throw new RegularFileChangedError(path);
return actual.readRegularFile(path, options);
});
try {
const result = await readEnvironmentExportInputs(
files.manifestPath,
files.capturePath,
);
if (result.ok) throw new Error("Expected changed input refusal");
expect(projectAnalysisError(result.error)).toMatchObject({
code: "invalid_request",
details: {
operation: "environment-export",
issues: [{ path: [role], reason: "invalid_value" }],
},
});
} finally {
reader.mockImplementation(actual.readRegularFile);
}
},
);
it("reads each file once as the bytes on disk and the value they parse to", async () => {
const root = await createTestTempDirectory("rea-environment-inputs-");
const fixture = environmentServeFixture();
@@ -12,6 +12,7 @@ import {
} from "../../domain/analysisErrorCore.js";
import type { JsonValue } from "../../domain/jsonValue.js";
import { err, ok, type Result } from "../../domain/result.js";
import { RegularFileChangedError } from "../../filesystem/RegularFile.js";
import { sealOwnedJsonInput } from "../OwnedJsonInput.js";
import { nativeJsonParseRequiredBytes } from "../JsonInputFile.js";
import { readRegularFile } from "../RegularFileRead.js";
@@ -219,6 +220,18 @@ const readInput = async (
});
} catch (cause: unknown) {
if (cause instanceof AnalysisResourceConstraintError) return err(cause);
if (cause instanceof RegularFileChangedError)
return err(
inputError(
{
path: [role],
reason: "invalid_value",
expected: "one stable regular file snapshot",
message: `The ${role} file changed while it was read.`,
},
`${path} changed while being read; retry with stable input files.`,
),
);
if (NOT_A_FILE_CODES.has(systemCode(cause) ?? ""))
return err(
inputError(