478 lines
14 KiB
TypeScript
478 lines
14 KiB
TypeScript
import { mkdtemp, rm } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
readReconstructionCoverageWorkspace,
|
|
writeReconstructionCoverageWorkspace,
|
|
} from "../src/application/ReconstructionCoverageWorkspaceStore.js";
|
|
import {
|
|
commitReconstructionCoverage,
|
|
queryReconstructionCoverage,
|
|
} from "../src/application/ReconstructionCoverageService.js";
|
|
import type { EvidenceFilePolicy } from "../src/domain/evidenceBundle.js";
|
|
import {
|
|
createReconstructionCoverageWorkspace,
|
|
createReconstructionVerifierContract,
|
|
evaluateReconstructionClosure,
|
|
parseReconstructionCoverageWorkspace,
|
|
} from "../src/domain/reconstructionCoverage.js";
|
|
import { createEvidence } from "../src/domain/evidence.js";
|
|
import { createEvidenceBundle } from "../src/domain/evidenceBundle.js";
|
|
|
|
const digest = (character: string): string => character.repeat(64);
|
|
const evidenceRecords = ["1", "2", "3", "4", "5"].map((character) =>
|
|
createEvidence(
|
|
undefined,
|
|
{ id: "fixture", name: "Fixture", version: "1" },
|
|
{
|
|
predicateType: "rea.coverage-fixture/v1",
|
|
operation: `fixture-${character}`,
|
|
parameters: {},
|
|
result: { character },
|
|
},
|
|
),
|
|
);
|
|
const evidence = (character: string): string => {
|
|
const record = evidenceRecords.find(
|
|
({ operation }) => operation === `fixture-${character}`,
|
|
);
|
|
if (record === undefined) throw new Error("Missing fixture Evidence");
|
|
return record.evidence_id;
|
|
};
|
|
const now = Date.parse("2026-07-16T12:00:00.000Z");
|
|
|
|
const completeWorkspace = () => {
|
|
const contract = createReconstructionVerifierContract({
|
|
verifier_id: "verify.cli.help",
|
|
claim_ids: ["claim.cli.help"],
|
|
dimensions: ["output", "exit"],
|
|
authority: "controlled-replay",
|
|
max_age_ms: 86_400_000,
|
|
minimum_repeats: 2,
|
|
normalization_sha256: digest("4"),
|
|
normalization_removes_dimensions: false,
|
|
});
|
|
return createReconstructionCoverageWorkspace({
|
|
name: "fixture",
|
|
revision: 1,
|
|
previous_revision_sha256: null,
|
|
evidence_bundle: createEvidenceBundle(evidenceRecords),
|
|
artifacts: [
|
|
{
|
|
artifact_id: "authority.v1",
|
|
artifact_sha256: digest("1"),
|
|
version: "1.0.0",
|
|
environment_sha256: digest("2"),
|
|
evidence_ids: [evidence("1")],
|
|
},
|
|
],
|
|
surfaces: [
|
|
{
|
|
surface_id: "cli.help",
|
|
family: "cli-command",
|
|
artifact_id: "authority.v1",
|
|
occurrence_id: "occ-help",
|
|
location: "bin/app --help",
|
|
authority: "observed",
|
|
dependency_surface_ids: [],
|
|
evidence_ids: [evidence("2")],
|
|
},
|
|
],
|
|
owners: [
|
|
{
|
|
surface_id: "cli.help",
|
|
ownership: {
|
|
disposition: "implemented",
|
|
owner_path: "src/cli.ts",
|
|
owner_export: "registerHelp",
|
|
owner_sha256: digest("3"),
|
|
path_state: "present",
|
|
package_state: "distributed",
|
|
authority_route: "none",
|
|
},
|
|
},
|
|
],
|
|
claims: [
|
|
{
|
|
claim_id: "claim.cli.help",
|
|
title: "Help output and exit behavior match",
|
|
kind: "behavioral",
|
|
surface_ids: ["cli.help"],
|
|
required_dimensions: ["output", "exit"],
|
|
required_authority: "controlled-replay",
|
|
},
|
|
],
|
|
verifier_contracts: [contract],
|
|
verifier_results: [
|
|
{
|
|
verifier_id: contract.verifier_id,
|
|
contract_sha256: contract.contract_sha256,
|
|
observed_at: "2026-07-16T11:00:00.000Z",
|
|
status: "pass",
|
|
covered_claim_ids: ["claim.cli.help"],
|
|
covered_dimensions: ["output", "exit"],
|
|
artifact_sha256s: [digest("1")],
|
|
owner_sha256s: [digest("3")],
|
|
normalization_sha256: digest("4"),
|
|
repeats: 2,
|
|
evidence_ids: [evidence("3")],
|
|
},
|
|
],
|
|
residual_unknown_ids: [],
|
|
contradictions: [],
|
|
package_proofs: [
|
|
{
|
|
proof_id: "proof.clean-install",
|
|
kind: "clean-install",
|
|
status: "pass",
|
|
artifact_sha256s: [digest("1")],
|
|
evidence_ids: [evidence("4")],
|
|
},
|
|
{
|
|
proof_id: "proof.authority-independence",
|
|
kind: "authority-independence",
|
|
status: "pass",
|
|
artifact_sha256s: [digest("1")],
|
|
evidence_ids: [evidence("5")],
|
|
},
|
|
],
|
|
boundaries: [
|
|
{
|
|
boundary_id: "replacement.cli",
|
|
title: "CLI replacement",
|
|
required_surface_ids: ["cli.help"],
|
|
required_claim_ids: ["claim.cli.help"],
|
|
required_package_proof_kinds: [
|
|
"clean-install",
|
|
"authority-independence",
|
|
],
|
|
allowed_dispositions: [],
|
|
allowed_unknown_ids: [],
|
|
},
|
|
],
|
|
});
|
|
};
|
|
|
|
describe("reconstruction coverage closure", () => {
|
|
it("returns ready only when ownership, verification, package, and authority closure pass", () => {
|
|
const workspace = completeWorkspace();
|
|
|
|
expect(
|
|
evaluateReconstructionClosure(workspace, "replacement.cli", now),
|
|
).toMatchObject({
|
|
status: "ready",
|
|
summary: { required_surfaces: 1, required_claims: 1, reasons: 0 },
|
|
evidence_ids: [
|
|
evidence("2"),
|
|
evidence("3"),
|
|
evidence("4"),
|
|
evidence("5"),
|
|
].sort(),
|
|
});
|
|
expect(parseReconstructionCoverageWorkspace(workspace)).toEqual(workspace);
|
|
});
|
|
|
|
it("keeps an incomplete inventory partial despite every registered verifier passing", () => {
|
|
const workspace = completeWorkspace();
|
|
const {
|
|
revision_sha256: _revisionSha256,
|
|
workspace_id: _workspaceId,
|
|
schema_version: _schemaVersion,
|
|
...semantic
|
|
} = workspace;
|
|
const boundary = workspace.boundaries[0];
|
|
if (boundary === undefined) throw new Error("Expected fixture boundary");
|
|
const incomplete = createReconstructionCoverageWorkspace({
|
|
...semantic,
|
|
revision: 2,
|
|
previous_revision_sha256: workspace.revision_sha256,
|
|
boundaries: [
|
|
{
|
|
...boundary,
|
|
required_surface_ids: ["cli.help", "cli.version"],
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(
|
|
evaluateReconstructionClosure(incomplete, "replacement.cli", now),
|
|
).toMatchObject({
|
|
status: "partial",
|
|
reasons: [
|
|
expect.objectContaining({
|
|
code: "surface-missing",
|
|
subject_id: "cli.version",
|
|
}),
|
|
],
|
|
recommended_probes: [
|
|
{
|
|
operation: "update_authoritative_inventory",
|
|
subject_id: "cli.version",
|
|
rationale:
|
|
"Required surface is absent from the authoritative inventory.",
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it("invalidates stale verifier contracts and detected authority routing", () => {
|
|
const workspace = completeWorkspace();
|
|
const owner = workspace.owners[0];
|
|
if (owner === undefined || owner.ownership.disposition !== "implemented")
|
|
throw new Error("Expected implemented fixture owner");
|
|
const {
|
|
revision_sha256: _revisionSha256,
|
|
workspace_id: _workspaceId,
|
|
schema_version: _schemaVersion,
|
|
...semantic
|
|
} = workspace;
|
|
const changed = createReconstructionCoverageWorkspace({
|
|
...semantic,
|
|
revision: 2,
|
|
previous_revision_sha256: workspace.revision_sha256,
|
|
owners: [
|
|
{
|
|
...owner,
|
|
ownership: {
|
|
...owner.ownership,
|
|
owner_sha256: digest("9"),
|
|
path_state: "present",
|
|
package_state: "distributed",
|
|
authority_route: "detected",
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
const result = evaluateReconstructionClosure(
|
|
changed,
|
|
"replacement.cli",
|
|
now,
|
|
);
|
|
expect(result.status).toBe("failed");
|
|
expect(result.reasons).toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({ code: "authority-routing-detected" }),
|
|
expect.objectContaining({ code: "verifier-result-incompatible" }),
|
|
]),
|
|
);
|
|
});
|
|
|
|
it("never lets mock-strength or stale results satisfy stronger current claims", () => {
|
|
const workspace = completeWorkspace();
|
|
const {
|
|
revision_sha256: _revisionSha256,
|
|
workspace_id: _workspaceId,
|
|
schema_version: _schemaVersion,
|
|
...semantic
|
|
} = workspace;
|
|
const stale = createReconstructionCoverageWorkspace({
|
|
...semantic,
|
|
revision: 2,
|
|
previous_revision_sha256: workspace.revision_sha256,
|
|
verifier_results: workspace.verifier_results.map((result) => ({
|
|
...result,
|
|
observed_at: "2026-07-01T00:00:00.000Z",
|
|
})),
|
|
});
|
|
|
|
expect(
|
|
evaluateReconstructionClosure(stale, "replacement.cli", now),
|
|
).toMatchObject({
|
|
status: "unknown",
|
|
reasons: [expect.objectContaining({ code: "verifier-result-stale" })],
|
|
});
|
|
});
|
|
|
|
it("orders offset-bearing verifier timestamps chronologically", () => {
|
|
const workspace = completeWorkspace();
|
|
const result = workspace.verifier_results[0];
|
|
if (result === undefined)
|
|
throw new Error("Expected fixture verifier result");
|
|
const {
|
|
revision_sha256: _revisionSha256,
|
|
workspace_id: _workspaceId,
|
|
schema_version: _schemaVersion,
|
|
...semantic
|
|
} = workspace;
|
|
const changed = createReconstructionCoverageWorkspace({
|
|
...semantic,
|
|
revision: 2,
|
|
previous_revision_sha256: workspace.revision_sha256,
|
|
verifier_results: [
|
|
{ ...result, observed_at: "2026-07-16T08:00:00.000Z" },
|
|
{
|
|
...result,
|
|
observed_at: "2026-07-16T04:00:00.000-05:00",
|
|
status: "fail",
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(
|
|
evaluateReconstructionClosure(changed, "replacement.cli", now),
|
|
).toMatchObject({
|
|
status: "failed",
|
|
reasons: [expect.objectContaining({ code: "verifier-failed" })],
|
|
});
|
|
});
|
|
|
|
it("rejects verifier observations from the future", () => {
|
|
const workspace = completeWorkspace();
|
|
const result = workspace.verifier_results[0];
|
|
if (result === undefined)
|
|
throw new Error("Expected fixture verifier result");
|
|
const {
|
|
revision_sha256: _revisionSha256,
|
|
workspace_id: _workspaceId,
|
|
schema_version: _schemaVersion,
|
|
...semantic
|
|
} = workspace;
|
|
const changed = createReconstructionCoverageWorkspace({
|
|
...semantic,
|
|
revision: 2,
|
|
previous_revision_sha256: workspace.revision_sha256,
|
|
verifier_results: [
|
|
{ ...result, observed_at: "2026-07-17T12:00:00.000Z" },
|
|
],
|
|
});
|
|
|
|
expect(
|
|
evaluateReconstructionClosure(changed, "replacement.cli", now),
|
|
).toMatchObject({
|
|
status: "unknown",
|
|
reasons: [expect.objectContaining({ code: "verifier-result-stale" })],
|
|
});
|
|
});
|
|
|
|
it("rejects green results and package proofs that omit current commitments", () => {
|
|
const workspace = completeWorkspace();
|
|
const {
|
|
revision_sha256: _revisionSha256,
|
|
workspace_id: _workspaceId,
|
|
schema_version: _schemaVersion,
|
|
...semantic
|
|
} = workspace;
|
|
const incomplete = createReconstructionCoverageWorkspace({
|
|
...semantic,
|
|
revision: 2,
|
|
previous_revision_sha256: workspace.revision_sha256,
|
|
verifier_results: workspace.verifier_results.map((result) => ({
|
|
...result,
|
|
owner_sha256s: [],
|
|
})),
|
|
package_proofs: workspace.package_proofs.map((proof) => ({
|
|
...proof,
|
|
artifact_sha256s: [digest("8")],
|
|
})),
|
|
});
|
|
|
|
const result = evaluateReconstructionClosure(
|
|
incomplete,
|
|
"replacement.cli",
|
|
now,
|
|
);
|
|
expect(result.status).toBe("unknown");
|
|
expect(result.reasons).toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({ code: "verifier-result-incompatible" }),
|
|
expect.objectContaining({ code: "package-proof-unknown" }),
|
|
]),
|
|
);
|
|
});
|
|
|
|
it("persists owner-only revisions with CAS and digest-chain enforcement", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "rea-coverage-workspace-"));
|
|
const path = join(root, "coverage.json");
|
|
const first = completeWorkspace();
|
|
const filePolicy: EvidenceFilePolicy = {
|
|
roots: [root],
|
|
maxBytes: 64 * 1024 * 1024,
|
|
maxDepth: 64,
|
|
maxStringLength: 1024 * 1024,
|
|
maxNodes: 1_000_000,
|
|
};
|
|
try {
|
|
const written = await writeReconstructionCoverageWorkspace(
|
|
first,
|
|
path,
|
|
null,
|
|
filePolicy,
|
|
);
|
|
expect(written.ok).toBe(true);
|
|
expect(
|
|
await readReconstructionCoverageWorkspace(path, filePolicy),
|
|
).toEqual({ ok: true, value: first });
|
|
|
|
const stale = await writeReconstructionCoverageWorkspace(
|
|
first,
|
|
path,
|
|
null,
|
|
filePolicy,
|
|
);
|
|
expect(stale).toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
_tag: "InvestigationWorkspaceError",
|
|
reason: "revision-conflict",
|
|
},
|
|
});
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("shares commit and fail-closed query behavior across adapters", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "rea-coverage-service-"));
|
|
const path = join(root, "coverage.json");
|
|
const workspace = completeWorkspace();
|
|
const filePolicy: EvidenceFilePolicy = {
|
|
roots: [root],
|
|
maxBytes: 64 * 1024 * 1024,
|
|
maxDepth: 64,
|
|
maxStringLength: 1024 * 1024,
|
|
maxNodes: 1_000_000,
|
|
};
|
|
try {
|
|
const committed = await commitReconstructionCoverage(
|
|
{
|
|
approved: true,
|
|
workspace_path: path,
|
|
expected_revision: null,
|
|
workspace,
|
|
},
|
|
filePolicy,
|
|
);
|
|
expect(committed.ok && committed.value).toMatchObject({
|
|
revision: 1,
|
|
revision_sha256: workspace.revision_sha256,
|
|
evidence_records: 5,
|
|
});
|
|
const queried = await queryReconstructionCoverage(
|
|
{ workspace_path: path, boundary_id: "replacement.cli" },
|
|
filePolicy,
|
|
now,
|
|
);
|
|
expect(queried.ok && queried.value).toMatchObject({ status: "ready" });
|
|
|
|
const controller = new AbortController();
|
|
controller.abort();
|
|
const cancelled = await queryReconstructionCoverage(
|
|
{ workspace_path: path, boundary_id: "replacement.cli" },
|
|
filePolicy,
|
|
now,
|
|
{ signal: controller.signal },
|
|
);
|
|
expect(cancelled).toMatchObject({
|
|
ok: false,
|
|
error: { _tag: "AnalysisCancelledError" },
|
|
});
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|