fix: fail closed in release drill verification
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { verifyRollbackReleaseCoherence } from "../../scripts/drill-runbook.ts";
|
||||
import { verifyReleaseRuntimeCoherence } from "../../scripts/lib/release-runtime-coherence.ts";
|
||||
import { verifyReleaseArtifactsCoherence } from "../../scripts/verify-release.ts";
|
||||
import type { InstalledContractPackageIdentity } from "../../src/contracts/external-contract-runtime.ts";
|
||||
import { computeContractSetDigest } from "../../src/contracts/contract-set-canonical.ts";
|
||||
import type {
|
||||
@@ -98,6 +98,19 @@ async function releaseV2With(
|
||||
};
|
||||
}
|
||||
|
||||
function artifactReader(
|
||||
entries: Readonly<Record<string, unknown | Error>>,
|
||||
): (path: string) => Promise<unknown> {
|
||||
return async (path) => {
|
||||
const value = entries[path];
|
||||
if (value === undefined) {
|
||||
throw Object.assign(new Error(`missing ${path}`), { code: "ENOENT" });
|
||||
}
|
||||
if (value instanceof Error) throw value;
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
describe("release coherence", () => {
|
||||
it("owns all nine release tokens and keeps builtAt diagnostic-only", () => {
|
||||
// §5.2 adds contractSetDigest beside the legacy apiContractVersion scalar.
|
||||
@@ -234,17 +247,25 @@ describe("release coherence", () => {
|
||||
];
|
||||
|
||||
for (const fixture of matrix) {
|
||||
const input = {
|
||||
release: fixture.release,
|
||||
runtime: fixture.runtime,
|
||||
contractPackages,
|
||||
};
|
||||
const input = { release: fixture.release, runtime: fixture.runtime };
|
||||
const verifierVerdict = (
|
||||
await verifyReleaseRuntimeCoherence(input)
|
||||
).compatible;
|
||||
await verifyReleaseArtifactsCoherence({
|
||||
readArtifact: artifactReader({
|
||||
"dist/release-manifest.json": input.release,
|
||||
"dist/config.json": input.runtime,
|
||||
}),
|
||||
contractPackages,
|
||||
})
|
||||
).coherence.compatible;
|
||||
const rollbackDrillVerdict = (
|
||||
await verifyRollbackReleaseCoherence(input)
|
||||
).compatible;
|
||||
await verifyRollbackReleaseCoherence({
|
||||
readArtifact: artifactReader({
|
||||
"dist/release-manifest.json": fixture.release,
|
||||
"dist/config.json": fixture.runtime,
|
||||
}),
|
||||
contractPackages,
|
||||
})
|
||||
).coherence.compatible;
|
||||
expect(verifierVerdict, `${fixture.name}: verifier`).toBe(
|
||||
fixture.expectedCompatible,
|
||||
);
|
||||
@@ -256,4 +277,49 @@ describe("release coherence", () => {
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("falls back to public rollback artifacts only when primary dist is absent", async () => {
|
||||
const exactV2 = await releaseV2With(contractPackages);
|
||||
const tamperedPrimary = await releaseV2With(contractPackages.slice(0, 1));
|
||||
const validPublic = {
|
||||
"public/release-manifest.json": exactV2,
|
||||
"public/config.json": runtimeV2,
|
||||
};
|
||||
const unavailablePrimary = [
|
||||
new SyntaxError("invalid primary JSON"),
|
||||
Object.assign(new Error("unreadable primary"), { code: "EACCES" }),
|
||||
{ ...exactV2, unexpected: "tampered" },
|
||||
];
|
||||
|
||||
for (const primaryFailure of unavailablePrimary) {
|
||||
await expect(
|
||||
verifyRollbackReleaseCoherence({
|
||||
readArtifact: artifactReader({
|
||||
"dist/release-manifest.json": primaryFailure,
|
||||
"dist/config.json": runtimeV2,
|
||||
...validPublic,
|
||||
}),
|
||||
contractPackages,
|
||||
}),
|
||||
).rejects.toBeDefined();
|
||||
}
|
||||
|
||||
await expect(
|
||||
verifyRollbackReleaseCoherence({
|
||||
readArtifact: artifactReader({
|
||||
"dist/release-manifest.json": tamperedPrimary,
|
||||
"dist/config.json": runtimeV2,
|
||||
...validPublic,
|
||||
}),
|
||||
contractPackages,
|
||||
}),
|
||||
).resolves.toMatchObject({ coherence: { compatible: false } });
|
||||
|
||||
await expect(
|
||||
verifyRollbackReleaseCoherence({
|
||||
readArtifact: artifactReader(validPublic),
|
||||
contractPackages,
|
||||
}),
|
||||
).resolves.toMatchObject({ coherence: { compatible: true } });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user