Files
gstack/lib/cso/verification.ts
T
garrytan 42e53413da feat: require a zero-error product typecheck and a test type-debt ratchet
Adds tsconfig.json (strict) over product code, fixes its remaining 90
diagnostics (type-only, interface corrections, and explicit narrowing),
and adds a typecheck job to the required free-tests aggregate running
bun run typecheck, the test-code ratchet (identity -> count baseline, fails
on new, repeated, or unlocked fixed diagnostics), and the lib/cso format
check. Reuses fixes from #2447 where they still applied.
2026-09-29 14:34:02 +00:00

2171 lines
87 KiB
TypeScript

import * as fs from 'node:fs';
import { randomBytes } from 'node:crypto';
import { spawn } from 'node:child_process';
import { basename, dirname, join } from 'node:path';
import {
AssertionWitnessBinding,
AssertionWitnessReceipt,
CsoError,
PreparationProof,
RepairBundle,
RepairReviewArtifact,
SnapshotManifest,
VerificationManifest,
VerificationObservation,
VerificationRequest,
canonical,
relativePath,
sha256,
snapshotPathHandleId,
snapshotPathId,
validateVerificationObservation,
validateVerificationRequest,
} from './contracts';
import { QualifiedRuntime } from './runtime-catalog';
import { inspectPreparation, type CsoStack } from './preparation';
import { containedFile } from './snapshot';
import { DockerEndpoint, DockerGroup } from './docker';
import type { PreparedDatabaseContract } from './preparation-executor';
import { redact, sanitizeHelperForJson } from './process';
import { secureDirectory, writeJsonExclusive } from './state';
import {
AssertionWitnessHandle,
AssertionWitnessSession,
WitnessedVerificationResult,
assertionWitnessPairHash,
testExecutionPassed,
validateStoredAssertionWitnessReceipt,
witnessObservationHash,
} from './witness';
export { testExecutionPassed } from './witness';
export interface VerificationExecutor {
observe(
source: string,
phase: 'before' | 'after',
request: VerificationRequest,
runtime: QualifiedRuntime,
verifier: QualifiedRuntime,
work: string,
control: string,
execution?: { environment: Record<string, string>; database?: PreparedDatabaseContract },
testEvidence?: { minimumPassingTests: number[] },
witness?: AssertionWitnessHandle,
): Promise<VerificationObservation | WitnessedVerificationResult>;
}
export interface FailedVerificationAttempt {
schemaVersion: 3;
artifactKind: 'repair_candidate';
id: string;
runId: string;
findingId: string;
createdAt: string;
bundleIssued: false;
runtime: { image: string; platform: string; profile: string };
policyHash: string;
requestHash: string;
harnessHash: string;
sourceHash: string;
request: VerificationRequest;
patchHash: string;
testToolchain: 'runtime' | 'project';
testCompletionAssurance: 'self_reported';
preparationHash?: string;
before: VerificationObservation;
after?: VerificationObservation;
reproduction: 'blocked' | 'inconclusive' | 'disproved' | 'reproduced';
repair: 'failed' | 'proposed';
failure: { code: string; message: string };
}
export class VerificationAttemptError extends CsoError {
constructor(
public causeError: CsoError,
public attempt: FailedVerificationAttempt,
) {
super(causeError.code, `${causeError.message}; before-phase evidence retained as attempt ${attempt.id}`);
this.name = 'VerificationAttemptError';
}
}
async function attemptGuard(
runDir: string,
work: string,
watchdog: string,
deadline: number,
): Promise<() => Promise<void>> {
const control = secureDirectory(join(runDir, 'supervision', basename(work)));
secureDirectory(work);
const ready = join(control, 'attempt.ready'),
terminal = join(control, 'attempt.terminal'),
stopped = join(control, 'attempt.stopped');
const child = spawn(
watchdog,
[
'--attempt-owner',
String(process.pid),
'--deadline',
String(Math.ceil(deadline / 1000)),
'--control-dir',
control,
'--work-root',
work,
'--run-root',
runDir,
],
{ cwd: control, env: { PATH: '/usr/bin:/bin' }, detached: true, stdio: 'ignore' },
);
let failed = false;
child.once('error', () => {
failed = true;
});
child.unref();
for (let i = 0; i < 100 && !failed && !fs.existsSync(ready); i++)
await new Promise((resolve) => setTimeout(resolve, 10));
let alive = false;
try {
if (child.pid) {
process.kill(child.pid, 0);
alive = true;
}
} catch {}
if (failed || !alive || !fs.existsSync(ready)) {
try {
if (child.pid) process.kill(child.pid, 'SIGKILL');
} catch {}
fs.rmSync(work, { recursive: true, force: true });
throw new CsoError('ISOLATION_FAILED', 'Attempt execution-copy watchdog failed its startup handshake');
}
return async () => {
fs.rmSync(work, { recursive: true, force: true });
fs.writeFileSync(terminal, 'normal cleanup complete\n', { mode: 0o600, flag: 'wx' });
for (let i = 0; i < 100 && !fs.existsSync(stopped); i++)
await new Promise((resolve) => setTimeout(resolve, 10));
if (!fs.existsSync(stopped))
throw new CsoError('ISOLATION_FAILED', 'Attempt watchdog did not acknowledge execution-copy cleanup');
};
}
function allFiles(root: string, at = root, ignore: (path: string) => boolean = () => false): string[] {
const out: string[] = [];
for (const entry of fs.readdirSync(at, { withFileTypes: true })) {
const p = join(at, entry.name),
relative = p.slice(root.length + 1).replaceAll('\\', '/');
if (ignore(relative)) continue;
if (entry.isSymbolicLink() || (!entry.isDirectory() && !entry.isFile()))
throw new CsoError('UNSAFE_PATH', 'Execution copy contains a special file');
if (entry.isDirectory()) out.push(...allFiles(root, p, ignore));
else out.push(relative);
}
return out.sort();
}
export function treeHash(root: string, predicate: (path: string) => boolean = () => true): string {
return sha256(
canonical(
allFiles(root)
.filter(predicate)
.map((path) => {
const file = containedFile(root, path),
before = fs.lstatSync(file);
if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1)
throw new CsoError('UNSAFE_PATH', 'Execution copy contains a special or hard-linked file');
const body = fs.readFileSync(file),
after = fs.lstatSync(file);
if (
before.ino !== after.ino ||
before.dev !== after.dev ||
before.size !== after.size ||
before.mtimeMs !== after.mtimeMs ||
before.ctimeMs !== after.ctimeMs
)
throw new CsoError('SNAPSHOT_RACE', `Execution copy changed while hashing: ${path}`);
return [path, sha256(body), before.mode & 0o777];
}),
),
);
}
const DEPENDENCY =
/(?:^|\/)(?:package(?:-lock)?\.json|npm-shrinkwrap\.json|bun\.lock|uv\.lock|requirements[^/]*\.txt|pyproject\.toml|setup\.(?:py|cfg)|Gemfile(?:\.lock)?|[^/]+\.gemspec)$/;
const CONFIG = /(?:^|\/)(?:config\/.+|\.env|Dockerfile|Procfile|.*\.(?:toml|ya?ml|json))$/;
export function fileEffect(path: string): 'source' | 'configuration' | 'dependency' {
return DEPENDENCY.test(path) ? 'dependency' : CONFIG.test(path) ? 'configuration' : 'source';
}
export function patchHash(request: Pick<VerificationRequest, 'changes'>): string {
return sha256(canonical(request.changes));
}
export function resolveVerificationRequestPaths(
manifest: SnapshotManifest,
request: VerificationRequest,
): VerificationRequest {
const resolve = (reference: string): string => {
const id = snapshotPathHandleId(reference);
if (!id) return relativePath(reference);
const entry = manifest.entries.find((item) => item.pathId === id);
if (entry) return entry.path;
const deleted = manifest.deletedPaths?.find((item) => item.pathId === id);
if (deleted) return deleted.path;
const changed = manifest.changedPaths?.find((path) => snapshotPathId(manifest.root, path) === id);
if (changed) return changed;
throw new CsoError(
'INVALID_SCHEMA',
`Verification path handle is outside the retained snapshot: ${reference}`,
);
};
const argument = (value: string): string => {
const direct = snapshotPathHandleId(value);
if (direct) return resolve(value);
if (value.startsWith('./') && snapshotPathHandleId(value.slice(2))) return `./${resolve(value.slice(2))}`;
return value;
};
const command = (value: VerificationRequest['start']): VerificationRequest['start'] => ({
...value,
args: value.args.map(argument),
});
return {
...request,
start: command(request.start),
existingTests: request.existingTests.map(command),
boundaryFiles: request.boundaryFiles.map(resolve),
testFiles: request.testFiles.map(resolve),
changes: request.changes.map((change) => ({ ...change, path: resolve(change.path) })),
};
}
export function reviewRequestHash(request: VerificationRequest): string {
const { artifactId, ...review } = request.review;
return sha256(canonical({ ...request, review }));
}
export function reviewArtifactIdentity(artifact: RepairReviewArtifact): string {
const { id, ...bound } = artifact;
return sha256(canonical(bound)).slice(0, 32);
}
export function makeReviewArtifact(
runId: string,
request: VerificationRequest,
producer: string,
): RepairReviewArtifact {
if (!producer || producer.length > 200 || producer === request.review.reviewer)
throw new CsoError(
'INVALID_SCHEMA',
'Repair producer and independent reviewer identities must be distinct',
);
if (!request.review.independent)
throw new CsoError('INVALID_SCHEMA', 'Repair review must be explicitly independent');
const artifact: RepairReviewArtifact = {
schemaVersion: 3,
id: '',
runId,
findingId: request.findingId,
createdAt: new Date().toISOString(),
producer,
reviewer: request.review.reviewer,
assurance: 'self_attested',
requestHash: reviewRequestHash(request),
patchHash: patchHash(request),
rootCauseRepaired: request.review.rootCauseRepaired,
featurePreserved: request.review.featurePreserved,
boundaryMocks: request.review.boundaryMocks,
rationale: request.review.rationale,
};
artifact.id = reviewArtifactIdentity(artifact);
return artifact;
}
export function validateReviewArtifact(
value: unknown,
runId: string,
request: VerificationRequest,
): RepairReviewArtifact {
const artifact = value as RepairReviewArtifact;
if (
!artifact ||
artifact.schemaVersion !== 3 ||
artifact.assurance !== 'self_attested' ||
artifact.runId !== runId ||
artifact.findingId !== request.findingId ||
artifact.id !== request.review.artifactId ||
reviewArtifactIdentity(artifact) !== artifact.id ||
artifact.requestHash !== reviewRequestHash(request) ||
artifact.patchHash !== patchHash(request) ||
artifact.reviewer !== request.review.reviewer ||
artifact.producer === artifact.reviewer ||
artifact.rootCauseRepaired !== request.review.rootCauseRepaired ||
artifact.featurePreserved !== request.review.featurePreserved ||
artifact.boundaryMocks !== request.review.boundaryMocks ||
artifact.rationale !== request.review.rationale
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Self-attested repair-review artifact does not bind this request',
);
return artifact;
}
export function verificationIdentity(manifest: VerificationManifest): string {
const { id, ...bound } = manifest;
return sha256(canonical(bound)).slice(0, 32);
}
export function verificationHarnessHash(request: VerificationRequest, sourceRoot: string): string {
const testInputs = request.testFiles.map((path) => {
const file = containedFile(sourceRoot, path);
if (!fs.existsSync(file))
throw new CsoError('INCOMPATIBLE_INPUT', `Immutable existing-test input is missing: ${path}`);
const stat = fs.lstatSync(file);
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1)
throw new CsoError('UNSAFE_PATH', `Immutable existing-test input is unsafe: ${path}`);
return [path, sha256(fs.readFileSync(file)), stat.mode & 0o777];
});
return sha256(
canonical({
port: request.port,
start: request.start,
legitimate: request.legitimate,
security: request.security,
existingTests: request.existingTests,
testInputs,
}),
);
}
export interface CanonicalTestPlan {
commands: VerificationRequest['existingTests'];
files: string[];
kind: string;
toolchain: 'runtime' | 'project';
minimumPassingTests: number[];
signature: string;
}
export interface CanonicalStartPlan {
command: VerificationRequest['start'];
kind: string;
signature: string;
entrypointFiles: string[];
}
const TEST_TREE = /(?:^|\/)(?:test|tests|__tests__|spec|fixtures|__fixtures__|testdata)(?:\/|$)/;
const NODE_TEST_CONFIG =
/(?:^|\/)(?:(?:jest|vitest|vite|playwright|cypress|karma|babel|ava|webpack)\.(?:config|conf)\.[^/]+|(?:jest|vitest|playwright|cypress|babel|ava|webpack)\.config\.[^/]+|\.mocharc(?:\.[^/]+)?|\.babelrc(?:\.[^/]+)?|tsconfig(?:\.[^/]+)?\.json|bunfig\.toml)$/;
const BUN_RUNTIME_POLICY_ARGS = ['--no-install', '--config=/opt/cso/no-auto-install.toml'];
// -S prevents dependency-provided .pth startup code from running before the
// trusted bootstrap. Add the venv's fixed Linux purelib directory directly,
// without processing .pth files, and import each runner before application cwd.
const PYTHON_PURELIB =
"os.path.join(os.path.dirname(os.path.dirname(sys.executable)),'lib',f'python{sys.version_info.major}.{sys.version_info.minor}','site-packages')";
const PYTEST_BOOTSTRAP = `import os,sys;sys.path.append(${PYTHON_PURELIB});import pytest;sys.path.insert(0,os.getcwd());raise SystemExit(pytest.main(sys.argv[1:]))`;
const UNITTEST_BOOTSTRAP = `import os,sys,unittest;sys.path.append(${PYTHON_PURELIB});sys.path.insert(0,os.getcwd());unittest.main(module=None,argv=['unittest',*sys.argv[1:]])`;
const DJANGO_BOOTSTRAP = `import os,sys,runpy;sys.path.append(${PYTHON_PURELIB});import django;sys.path.insert(0,os.getcwd());sys.argv=['manage.py',*sys.argv[1:]];runpy.run_path('manage.py',run_name='__main__')`;
const FLASK_BOOTSTRAP = `import os,sys;sys.path.append(${PYTHON_PURELIB});from flask.cli import main as _cso_main;sys.path.insert(0,os.getcwd());sys.argv=['flask',*sys.argv[1:]];_cso_main()`;
const UVICORN_BOOTSTRAP = `import os,sys;sys.path.append(${PYTHON_PURELIB});from uvicorn.main import main as _cso_main;sys.path.insert(0,os.getcwd());sys.argv=['uvicorn',*sys.argv[1:]];_cso_main()`;
function fileText(root: string, path: string): string {
try {
return fs.readFileSync(containedFile(root, path), 'utf8');
} catch {
throw new CsoError('MISSING_INPUT', `Canonical test input is missing or unreadable: ${path}`);
}
}
function packageTestProjection(root: string, paths: string[]): unknown[] {
return paths
.filter((path) => /(?:^|\/)package\.json$/.test(path) && !TEST_TREE.test(path))
.map((path) => {
let value: Record<string, any>;
try {
value = JSON.parse(fileText(root, path));
} catch {
throw new CsoError('MISSING_INPUT', `Canonical package test configuration is invalid: ${path}`);
}
if (!value || typeof value !== 'object' || Array.isArray(value))
throw new CsoError('MISSING_INPUT', `Canonical package test configuration is invalid: ${path}`);
return {
path,
type: value.type ?? null,
workspaces: value.workspaces ?? null,
scripts: value.scripts ?? null,
jest: value.jest ?? null,
vitest: value.vitest ?? null,
mocha: value.mocha ?? null,
ava: value.ava ?? null,
nyc: value.nyc ?? null,
};
});
}
function withoutJsCommentsAndStrings(value: string): string {
return value.replace(
/\/\*[\s\S]*?\*\/|\/\/[^\r\n]*|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`/g,
(match) => ' '.repeat(match.length),
);
}
function assertJavascriptTestRegistrations(root: string, tests: string[]): number {
const code = tests.map((path) => withoutJsCommentsAndStrings(fileText(root, path))).join('\n');
if (/\b(?:fdescribe|fit)\s*\(|\b(?:describe|test|it)\s*\.\s*(?:only|concurrent\s*\.\s*only)\b/.test(code))
throw new CsoError('MISSING_INPUT', 'Canonical JavaScript tests cannot certify a focused-only suite');
const registrations = [
...code.matchAll(/\b(?:test|it)\s*(?:\.\s*(?:concurrent|each)\s*(?:\([^)]*\))?)?\s*\(/g),
].length;
if (!registrations)
throw new CsoError(
'MISSING_INPUT',
'Canonical JavaScript tests need static evidence of at least one non-skipped test or it registration',
);
return registrations;
}
function boundedTestPaths(tests: string[]): string[] {
if (!tests.length) throw new CsoError('MISSING_INPUT', 'No canonical project test sources were found');
if (tests.length > 1000)
throw new CsoError(
'MISSING_INPUT',
'Canonical project test suite exceeds the 1,000-file verification limit',
);
const paths = tests.map((path) => `./${path}`);
if (paths.reduce((bytes, path) => bytes + Buffer.byteLength(path) + 1, 0) > 128 * 1024)
throw new CsoError(
'MISSING_INPUT',
'Canonical project test paths exceed the bounded direct-runner argument limit',
);
return paths;
}
function directPackageTest(
root: string,
stack: 'node' | 'bun',
manifest: Record<string, any>,
tests: string[],
configuration: string[],
): {
command: VerificationRequest['existingTests'][number];
kind: string;
runner: string;
toolchain: 'runtime' | 'project';
minimumPassingTests: number;
} {
const scripts = manifest.scripts;
if (!scripts || typeof scripts !== 'object' || Array.isArray(scripts))
throw new CsoError('MISSING_INPUT', `Canonical ${stack} package test scripts are missing or invalid`);
const script = scripts.test;
if (
typeof script !== 'string' ||
!script.trim() ||
script.length > 4096 ||
/no test specified|^\s*(?:true|:|exit\s+0)\s*$/i.test(script)
)
throw new CsoError('MISSING_INPUT', `Canonical ${stack} test script is missing or a placeholder`);
for (const hook of ['pretest', 'posttest']) {
const value = scripts[hook];
if (value !== undefined && typeof value !== 'string')
throw new CsoError('MISSING_INPUT', `Canonical ${stack} ${hook} lifecycle hook is invalid`);
if (typeof value === 'string' && value.trim())
throw new CsoError(
'MISSING_INPUT',
`Canonical ${stack} tests cannot certify through package lifecycle hooks; remove ${hook} or run the direct standard runner`,
);
}
if (/[;&|><`$()\\\r\n]/.test(script))
throw new CsoError(
'MISSING_INPUT',
`Canonical ${stack} tests require one recognized direct standard runner; local wrappers and shell composition are not admitted`,
);
const words = script.trim().split(/\s+/),
standard = ['jest', 'vitest', 'mocha', 'ava'],
paths = boundedTestPaths(tests),
minimumPassingTests = assertJavascriptTestRegistrations(root, tests);
if (canonical(words) === canonical(['node', '--test'])) {
return {
command: { executable: '/usr/local/bin/node', args: ['--test', '--test-reporter=tap', ...paths] },
kind: 'direct node --test with TAP count evidence',
runner: 'node',
toolchain: 'runtime',
minimumPassingTests,
};
}
if (canonical(words) === canonical(['bun', 'test'])) {
if (stack !== 'bun')
throw new CsoError(
'MISSING_INPUT',
'Canonical Node verification cannot depend on the Bun test runtime',
);
return {
command: { executable: '/usr/local/bin/bun', args: [...BUN_RUNTIME_POLICY_ARGS, 'test', ...paths] },
kind: 'direct bun test with automatic installation disabled',
runner: 'bun',
toolchain: 'runtime',
minimumPassingTests,
};
}
const runner =
words.length === 1 && standard.includes(words[0])
? words[0]
: words.length === 3 && words[0] === 'npx' && words[1] === '--no-install' && standard.includes(words[2])
? words[2]
: undefined;
if (!runner)
throw new CsoError(
'MISSING_INPUT',
`Canonical ${stack} tests require one recognized direct standard runner; local wrappers and shell composition are not admitted`,
);
const control = canonical({
embedded: manifest[runner] ?? null,
files: configuration
.filter((path) => NODE_TEST_CONFIG.test(path))
.map((path) => [path, fileText(root, path)]),
});
if (
/(?:collectOnly|dryRun|passWithNoTests|testNamePattern|\b(?:grep|fgrep|match)\b|--(?:collect-only|dry-run|grep|fgrep|match|passWithNoTests))/i.test(
control,
)
)
throw new CsoError(
'MISSING_INPUT',
`Canonical ${runner} configuration cannot focus, skip execution, or allow an empty suite`,
);
const args =
runner === 'jest'
? ['--runTestsByPath', '--passWithNoTests=false', '--json', ...paths]
: runner === 'vitest'
? ['run', '--passWithNoTests=false', '--reporter=verbose', ...paths]
: runner === 'mocha'
? ['--fail-zero', '--no-dry-run', '--forbid-only', '--reporter', 'json', ...paths]
: ['--tap', ...paths];
return {
command: { executable: `/work/node_modules/.bin/${runner}`, args },
kind: `direct local ${runner}`,
runner,
toolchain: 'project',
minimumPassingTests,
};
}
function directPackageStartEntrypoint(root: string, stack: 'node' | 'bun', script: string): string {
if (/[;&|><`$()\\\r\n]/.test(script))
throw new CsoError('MISSING_INPUT', `Canonical ${stack} startup cannot use shell composition`);
const words = script.trim().split(/\s+/),
runner = words.shift();
if (
runner !== stack ||
words.length !== 1 ||
!/^[A-Za-z0-9_./-]+\.(?:[cm]?[jt]s|jsx|tsx)$/.test(words[0]) ||
words[0].startsWith('/') ||
words[0].split('/').includes('..')
)
throw new CsoError(
'MISSING_INPUT',
`Canonical ${stack} package startup requires one direct contained ${stack} entrypoint`,
);
const path = relativePath(words[0]);
if (!executableSource(root, path))
throw new CsoError(
'MISSING_INPUT',
`Canonical ${stack} package startup entrypoint is missing or unsafe: ${path}`,
);
return path;
}
function pyprojectTestProjection(root: string, path: string): unknown {
try {
const value = Bun.TOML.parse(fileText(root, path)) as Record<string, any>;
return {
tool: { pytest: value?.tool?.pytest ?? null, coverage: value?.tool?.coverage ?? null },
projectScripts: value?.project?.scripts ?? null,
};
} catch {
throw new CsoError('MISSING_INPUT', 'Canonical Python test configuration is invalid: pyproject.toml');
}
}
export function canonicalTestPlan(sourceRoot: string, stack: CsoStack): CanonicalTestPlan {
const generated = (path: string) => {
const first = path.split('/')[0];
return stack === 'node'
? first === 'node_modules' || first === '.cso-npm-cache'
: stack === 'bun'
? first === 'node_modules' || first === '.cso-bun-cache'
: stack === 'python'
? first === '.venv' || first === '.cso-uv-cache' || path === '.gstack-cso-public-requirements.txt'
: path.startsWith('vendor/bundle/') || first === '.cso-bundle' || first === '.cso-gems';
};
const all = allFiles(sourceRoot, sourceRoot, generated);
let tests: string[] = [],
configuration: string[] = [],
commands: VerificationRequest['existingTests'] = [],
kind = '',
toolchain: 'runtime' | 'project' = 'runtime',
minimumPassingTests: number[] = [],
runnerEvidence: unknown = {};
if (stack === 'node' || stack === 'bun') {
let manifest: Record<string, any>;
try {
manifest = JSON.parse(fileText(sourceRoot, 'package.json'));
} catch {
throw new CsoError('MISSING_INPUT', `Canonical ${stack} package.json is missing or invalid`);
}
tests = all.filter((path) =>
/(?:^|\/)(?:test|tests|__tests__)\/.*\.(?:[cm]?js|tsx?|jsx)$|\.(?:test|spec)\.(?:[cm]?js|tsx?|jsx)$/.test(
path,
),
);
configuration = all.filter((path) => TEST_TREE.test(path) || NODE_TEST_CONFIG.test(path));
const direct = directPackageTest(sourceRoot, stack, manifest, tests, configuration);
commands = [direct.command];
kind = direct.kind;
toolchain = direct.toolchain;
minimumPassingTests = [direct.minimumPassingTests];
runnerEvidence = {
runner: direct.runner,
declaredScript: manifest.scripts.test,
packages: packageTestProjection(sourceRoot, all),
minimumPassingTests: direct.minimumPassingTests,
};
} else if (stack === 'python') {
tests = all.filter((path) =>
/(?:^|\/)(?:test|tests)\/.*\.py$|(?:^|\/)test_[^/]+\.py$|_test\.py$/.test(path),
);
configuration = all.filter(
(path) =>
TEST_TREE.test(path) ||
/(?:^|\/)(?:conftest\.py|\.?pytest\.ini|\.?pytest\.toml|setup\.cfg|tox\.ini|noxfile\.py)$/.test(path),
);
const bodies = tests.map((path) => fileText(sourceRoot, path)),
configBodies = configuration.map((path) => fileText(sourceRoot, path)),
pyproject = all.includes('pyproject.toml')
? pyprojectTestProjection(sourceRoot, 'pyproject.toml')
: null;
const pytestEvidence =
all.some((path) => /(?:^|\/)(?:conftest\.py|\.?pytest\.ini|\.?pytest\.toml)$/.test(path)) ||
[...bodies, ...configBodies].some(
(body) =>
/(?:^|\n)\s*(?:import pytest|from pytest\b|@pytest\.)/m.test(body) ||
/(?:^|\n)(?:async\s+)?def test_[A-Za-z0-9_]*\s*\(/m.test(body),
);
const unittestEvidence = bodies.some((body) =>
/(?:^|\n)\s*(?:import unittest|from unittest\b)|unittest\.TestCase|TestCase\s*\)/m.test(body),
);
if (!pytestEvidence && !unittestEvidence)
throw new CsoError(
'MISSING_INPUT',
'Python test runner is ambiguous; declare pytest evidence or a unittest suite',
);
const usePytest = pytestEvidence,
paths = boundedTestPaths(tests),
pytestControl = [...configBodies, canonical(pyproject)].join('\n');
if (
usePytest &&
/(?:--collect-only|\s--co\b|--setup-(?:only|plan)|--fixtures(?:-per-test)?|--no-summary|\baddopts[^\n]*(?:\s-k\b|\s-m\b|--ignore\b|--deselect\b|(?:^|\s)-q{2,}\b))/i.test(
pytestControl,
)
)
throw new CsoError(
'MISSING_INPUT',
'Canonical pytest configuration cannot collect only, focus, deselect, suppress its count, or skip test execution',
);
commands = [
{
executable: '/work/.venv/bin/python',
args: usePytest
? ['-I', '-S', '-c', PYTEST_BOOTSTRAP, '-q', '--color=no', '--', ...paths]
: ['-I', '-S', '-c', UNITTEST_BOOTSTRAP, ...paths],
},
];
kind = usePytest
? 'isolated prepared pytest with explicit files, positive summary, and no .pth startup'
: 'isolated standard-library unittest with explicit files and no .pth startup';
toolchain = usePytest ? 'project' : 'runtime';
minimumPassingTests = [1];
runnerEvidence = {
runner: usePytest ? 'pytest' : 'unittest',
bootstrap: usePytest ? PYTEST_BOOTSTRAP : UNITTEST_BOOTSTRAP,
siteInitialization: false,
reporter: usePytest ? 'quiet-positive-summary-no-color' : 'unittest-summary',
pyproject,
};
} else {
const specs = all.filter((path) => /(?:^|\/)spec\/.*_spec\.rb$/.test(path)),
rails = all.filter((path) => /(?:^|\/)test\/.*_test\.rb$/.test(path));
tests = [...specs, ...rails];
configuration = all.filter((path) => TEST_TREE.test(path) || /(?:^|\/)\.rspec(?:-local)?$/.test(path));
const rspecControl = configuration
.filter((path) => /(?:^|\/)\.rspec(?:-local)?$/.test(path))
.map((path) => fileText(sourceRoot, path))
.join('\n');
if (/--(?:dry-run|tag|example|pattern|exclude-pattern|only-failures|next-failure)\b/.test(rspecControl))
throw new CsoError(
'MISSING_INPUT',
'Canonical RSpec configuration cannot dry-run, focus, filter, or select only prior failures',
);
commands = [
...(specs.length
? [
{
executable: '/usr/local/bin/bundle',
args: ['exec', 'rspec', '--format', 'json', '--', ...boundedTestPaths(specs)],
},
]
: []),
...(rails.length
? [
{
executable: '/usr/local/bin/bundle',
args: ['exec', 'rails', 'test', '--no-color', ...boundedTestPaths(rails)],
},
]
: []),
];
kind = commands.map((command) => command.args.join(' ')).join(' + ');
toolchain = 'project';
minimumPassingTests = commands.map(() => 1);
runnerEvidence = {
rspec: specs.length > 0,
minitest: rails.length > 0,
reporters: specs.length
? ['rspec-json', ...(rails.length ? ['rails-summary-no-color'] : [])]
: ['rails-summary-no-color'],
};
}
tests = [...new Set(tests)].sort();
configuration = [...new Set(configuration)].sort();
if (!tests.length)
throw new CsoError('MISSING_INPUT', `No canonical ${stack} project test sources were found`);
const selected = [...new Set([...configuration, ...tests])].sort();
if (selected.length > 1000)
throw new CsoError(
'MISSING_INPUT',
'Canonical project test suite exceeds the 1,000-file verification limit',
);
if (
minimumPassingTests.length !== commands.length ||
minimumPassingTests.some((value) => !Number.isInteger(value) || value < 1)
)
throw new CsoError(
'MISSING_INPUT',
'Canonical test plan could not derive a positive execution-count floor',
);
return {
commands,
files: selected,
kind,
toolchain,
minimumPassingTests,
signature: sha256(
canonical({ stack, runnerEvidence, commands, files: selected, toolchain, minimumPassingTests }),
),
};
}
export function assertCanonicalTestPlan(
request: VerificationRequest,
sourceRoot: string,
stack: CsoStack,
): CanonicalTestPlan {
const plan = canonicalTestPlan(sourceRoot, stack);
if (
canonical(request.existingTests) !== canonical(plan.commands) ||
canonical([...request.testFiles].sort()) !== canonical(plan.files)
)
throw new CsoError(
'INVALID_SCHEMA',
`Existing tests must use the helper-derived full ${plan.kind} suite and its immutable inputs`,
);
return plan;
}
function executableSource(root: string, path: string): boolean {
try {
const file = containedFile(root, relativePath(path)),
stat = fs.lstatSync(file);
return stat.isFile() && !stat.isSymbolicLink() && stat.nlink === 1;
} catch {
return false;
}
}
function rejectPythonFrameworkShadows(root: string, framework: string, names: string[]): void {
for (const name of names)
for (const candidate of [`${name}.py`, name]) {
const file = containedFile(root, candidate);
if (fs.existsSync(file))
throw new CsoError(
'PREREQUISITE',
`Canonical ${framework} startup rejects root import shadow: ${candidate}`,
);
}
}
export function canonicalStartPlan(sourceRoot: string, stack: CsoStack, port: number): CanonicalStartPlan {
if (!Number.isInteger(port) || port < 1024 || port > 65535)
throw new CsoError(
'INVALID_SCHEMA',
'Canonical application start needs a loopback port from 1024 to 65535',
);
let command: VerificationRequest['start'],
kind: string,
entrypointFiles: string[] = [],
evidence: unknown;
if (stack === 'node' || stack === 'bun') {
let manifest: Record<string, any>;
try {
manifest = JSON.parse(fileText(sourceRoot, 'package.json'));
} catch {
throw new CsoError('MISSING_INPUT', `Canonical ${stack} package.json is missing or invalid`);
}
const start = manifest?.scripts?.start;
if (typeof start === 'string' && start.trim() && !/no start|^\s*(?:true|:|exit\s+0)\s*$/i.test(start)) {
for (const hook of ['prestart', 'poststart']) {
const value = manifest?.scripts?.[hook];
if (value !== undefined && typeof value !== 'string')
throw new CsoError('MISSING_INPUT', `Canonical ${stack} ${hook} lifecycle hook is invalid`);
if (typeof value === 'string' && value.trim())
throw new CsoError(
'MISSING_INPUT',
`Canonical ${stack} startup cannot certify through package lifecycle hooks; remove ${hook} or run the direct entrypoint`,
);
}
const entry = directPackageStartEntrypoint(sourceRoot, stack, start);
command = {
executable: stack === 'node' ? '/usr/local/bin/node' : '/usr/local/bin/bun',
args: stack === 'node' ? [entry] : [...BUN_RUNTIME_POLICY_ARGS, entry],
};
kind = `direct ${stack} package start`;
evidence = { script: start, entry };
entrypointFiles = ['package.json', entry];
} else {
const declared =
typeof manifest?.main === 'string' && manifest.main.length < 4096 ? manifest.main : undefined,
candidates = [
...(declared ? [declared] : []),
...'server.js,app.js,index.js,server.mjs,app.mjs,index.mjs'.split(','),
].filter((value, index, all) => all.indexOf(value) === index && executableSource(sourceRoot, value));
if (candidates.length !== 1)
throw new CsoError(
'MISSING_INPUT',
`Canonical ${stack} startup is ambiguous; declare one non-placeholder start script or one conventional main entrypoint`,
);
const entry = relativePath(candidates[0]);
command = {
executable: stack === 'node' ? '/usr/local/bin/node' : '/usr/local/bin/bun',
args: stack === 'node' ? [entry] : [...BUN_RUNTIME_POLICY_ARGS, entry],
};
kind = `${stack} ${entry}`;
evidence = { entry };
entrypointFiles = [entry];
}
} else if (stack === 'rails') {
entrypointFiles = ['config/application.rb', 'config/environment.rb'].filter((path) =>
executableSource(sourceRoot, path),
);
if (entrypointFiles.length !== 2)
throw new CsoError(
'MISSING_INPUT',
'Canonical Rails startup requires config/application.rb and config/environment.rb',
);
command = {
executable: '/usr/local/bin/bundle',
args: ['exec', 'rails', 'server', '-b', '127.0.0.1', '-p', String(port)],
};
kind = 'Rails loopback server';
evidence = { entrypointFiles };
} else {
const preparation = inspectPreparation(sourceRoot, 'python');
if (preparation.status !== 'ready')
throw new CsoError(
'PREREQUISITE',
preparation.prerequisites.map((item) => item.message).join('; ') ||
'Python dependency metadata is incomplete',
);
const dependencies = new Set(
preparation.inputs.map((input) => input.name.toLowerCase().replaceAll('_', '-')),
),
choices: Array<{
kind: string;
command: VerificationRequest['start'];
files: string[];
evidence: unknown;
}> = [];
if (dependencies.has('django') && executableSource(sourceRoot, 'manage.py')) {
rejectPythonFrameworkShadows(sourceRoot, 'Django', ['django']);
choices.push({
kind: 'isolated Django loopback server without .pth startup',
command: {
executable: '/work/.venv/bin/python',
args: ['-I', '-S', '-c', DJANGO_BOOTSTRAP, 'runserver', `127.0.0.1:${port}`, '--noreload'],
},
files: ['manage.py'],
evidence: {
framework: 'django',
bootstrap: DJANGO_BOOTSTRAP,
siteInitialization: false,
rootImportShadowsRejected: ['django.py', 'django/'],
},
});
}
for (const file of ['app.py', 'application.py', 'wsgi.py'])
if (dependencies.has('flask') && executableSource(sourceRoot, file)) {
const body = fileText(sourceRoot, file),
match = body.match(/(?:^|\n)\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*Flask\s*\(/m);
if (match) {
rejectPythonFrameworkShadows(sourceRoot, 'Flask', ['flask']);
choices.push({
kind: 'isolated Flask loopback server without .pth startup',
command: {
executable: '/work/.venv/bin/python',
args: [
'-I',
'-S',
'-c',
FLASK_BOOTSTRAP,
'--app',
`${file.replace(/\.py$/, '')}:${match[1]}`,
'run',
'--host',
'127.0.0.1',
'--port',
String(port),
],
},
files: [file],
evidence: {
framework: 'flask',
module: file,
symbol: match[1],
bootstrap: FLASK_BOOTSTRAP,
siteInitialization: false,
rootImportShadowsRejected: ['flask.py', 'flask/'],
},
});
}
}
for (const file of ['main.py', 'app.py', 'server.py'])
if (dependencies.has('fastapi') && dependencies.has('uvicorn') && executableSource(sourceRoot, file)) {
const body = fileText(sourceRoot, file),
match = body.match(/(?:^|\n)\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*FastAPI\s*\(/m);
if (match) {
rejectPythonFrameworkShadows(sourceRoot, 'FastAPI/Uvicorn', ['fastapi', 'uvicorn']);
choices.push({
kind: 'isolated FastAPI loopback server without .pth startup',
command: {
executable: '/work/.venv/bin/python',
args: [
'-I',
'-S',
'-c',
UVICORN_BOOTSTRAP,
`${file.replace(/\.py$/, '')}:${match[1]}`,
'--app-dir',
'/work',
'--host',
'127.0.0.1',
'--port',
String(port),
],
},
files: [file],
evidence: {
framework: 'fastapi',
module: file,
symbol: match[1],
bootstrap: UVICORN_BOOTSTRAP,
siteInitialization: false,
rootImportShadowsRejected: ['fastapi.py', 'fastapi/', 'uvicorn.py', 'uvicorn/'],
},
});
}
}
if (preparation.inputs.length === 0) {
const direct = ['app.py', 'application.py', 'server.py', 'main.py'].filter((file) =>
executableSource(sourceRoot, file),
);
if (direct.length === 1) {
const entry = direct[0];
choices.push({
kind: 'isolated standard-library Python application',
command: { executable: '/usr/local/bin/python', args: ['-I', entry] },
files: [entry],
evidence: { framework: 'standard-library', entry, isolatedMode: true, dependencyClosure: 'empty' },
});
}
}
const unique = choices.filter(
(choice, index) =>
choices.findIndex((other) => canonical(other.command) === canonical(choice.command)) === index,
);
if (unique.length !== 1)
throw new CsoError(
'MISSING_INPUT',
'Canonical Python startup is unavailable or ambiguous; use one supported Django, Flask, or FastAPI entrypoint with locked runtime dependencies',
);
({ command, kind, evidence } = unique[0]);
entrypointFiles = unique[0].files;
}
const entrypointEvidence = entrypointFiles.map((path) => {
const file = containedFile(sourceRoot, path),
stat = fs.lstatSync(file);
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1)
throw new CsoError('UNSAFE_PATH', `Canonical startup input is unsafe: ${path}`);
return { path, sha256: sha256(fs.readFileSync(file)), mode: stat.mode & 0o777 };
});
return {
command,
kind,
entrypointFiles,
signature: sha256(canonical({ stack, kind, evidence, command, entrypointEvidence })),
};
}
export function assertCanonicalStartPlan(
request: VerificationRequest,
sourceRoot: string,
stack: CsoStack,
): CanonicalStartPlan {
const plan = canonicalStartPlan(sourceRoot, stack, request.port);
if (canonical(request.start) !== canonical(plan.command))
throw new CsoError(
'INVALID_SCHEMA',
`Application start must use the helper-derived ${plan.kind} command`,
);
return plan;
}
export function preparePatchedSource(snapshot: string, target: string, request: VerificationRequest): void {
secureDirectory(target);
fs.cpSync(snapshot, target, {
recursive: true,
errorOnExist: false,
force: true,
preserveTimestamps: false,
});
for (const change of request.changes) {
const path = relativePath(change.path),
file = containedFile(target, path),
exists = fs.existsSync(file);
if (change.beforeSha256 === null && exists)
throw new CsoError('INCOMPATIBLE_INPUT', `Expected new patch path already exists: ${path}`);
if (change.beforeSha256 !== null && (!exists || sha256(fs.readFileSync(file)) !== change.beforeSha256))
throw new CsoError('INCOMPATIBLE_INPUT', `Patch preimage does not match: ${path}`);
const derived = fileEffect(path);
if (change.effect !== derived)
throw new CsoError('INVALID_SCHEMA', `${path} must be declared as ${derived}, not ${change.effect}`);
if (change.after === null) {
fs.unlinkSync(file);
continue;
}
const safe = redact(change.after);
if (safe !== change.after)
throw new CsoError(
'REDACTION_FAILED',
`Patch content for ${path} contains material that cannot enter a repair bundle`,
);
const mode = exists ? fs.statSync(file).mode & 0o777 : 0o600;
secureDirectory(dirname(file));
fs.writeFileSync(file, change.after, { mode });
}
}
export function certify(params: {
runId: string;
manifest: SnapshotManifest;
request: VerificationRequest;
identityRequest?: VerificationRequest;
runtime: QualifiedRuntime;
verifier: QualifiedRuntime;
before: VerificationObservation;
after: VerificationObservation;
beforeRoot: string;
afterRoot: string;
policyHash: string;
auditPolicyHash?: string;
archives: string[];
dependencyClosures?: { before: unknown; after: unknown };
preparation?: { before: PreparationProof; after: PreparationProof };
reviewArtifact?: RepairReviewArtifact;
startPlanHash?: string;
testPlanHash?: string;
testToolchain: 'runtime' | 'project';
minimumPassingTests?: number[];
witness?: { before: AssertionWitnessReceipt; after: AssertionWitnessReceipt };
}): { manifest: VerificationManifest; bundle?: RepairBundle } {
const { request } = params,
identityRequest = params.identityRequest ?? request,
pHash = patchHash(identityRequest),
harnessHash = verificationHarnessHash(request, params.beforeRoot),
afterHarnessHash = verificationHarnessHash(request, params.afterRoot),
fixturesHash = sha256(canonical(identityRequest.fixtures));
if (afterHarnessHash !== harnessHash)
throw new CsoError('ASSERTION_FAILED', 'Repair changed immutable existing-test inputs');
if (!['runtime', 'project'].includes(params.testToolchain))
throw new CsoError(
'INVALID_SCHEMA',
'Verification test toolchain must be helper-derived as runtime or project',
);
if (identityRequest.review.reviewedPatchHash !== pHash)
throw new CsoError('INVALID_SCHEMA', `Independent review binds the wrong patch hash; expected ${pHash}`);
const sourceAfter = treeHash(params.afterRoot),
dependenciesBefore = treeHash(params.beforeRoot, (p) => DEPENDENCY.test(p)),
dependenciesAfter = treeHash(params.afterRoot, (p) => DEPENDENCY.test(p)),
configurationBefore = treeHash(params.beforeRoot, (p) => CONFIG.test(p) && !DEPENDENCY.test(p)),
configurationAfter = treeHash(params.afterRoot, (p) => CONFIG.test(p) && !DEPENDENCY.test(p));
const mechanical =
params.before.booted &&
params.before.legitimate &&
params.before.security === 'intended_failure' &&
params.before.existingTests &&
params.after.booted &&
params.after.legitimate &&
params.after.security === 'pass' &&
params.after.existingTests;
const reviewGate =
identityRequest.review.independent &&
identityRequest.review.rootCauseRepaired &&
identityRequest.review.featurePreserved &&
!identityRequest.review.boundaryMocks;
// Application code shares the project test process and can forge reporter
// output or terminate the runner. The signed receipt authenticates the
// separate verifier assertions; project-test completion stays self-reported.
const testCompletionAssurance = 'self_reported' as const;
const reviewAssurance = params.reviewArtifact?.assurance ?? 'self_attested';
const inconclusive =
!params.before.booted ||
!params.before.legitimate ||
params.before.security === 'inconclusive' ||
!params.after.booted ||
params.after.security === 'inconclusive';
if (
params.preparation &&
(canonical(params.preparation.before.transformations) !==
canonical(params.preparation.after.transformations) ||
params.preparation.before.databaseHash !== params.preparation.after.databaseHash)
)
throw new CsoError('ASSERTION_FAILED', 'Repair changed the synthetic preparation or database boundary');
if (mechanical && reviewGate && params.testToolchain === 'project') {
if (request.changes.some((change) => change.effect === 'dependency'))
throw new CsoError(
'PREREQUISITE',
'Runtime-tested dependency repairs require a test runner pinned in the qualified runtime; project-installed test toolchains may change with the repair',
);
if (!params.preparation)
throw new CsoError(
'ASSERTION_FAILED',
'Project-installed test toolchains require before/after prepared dependency proofs',
);
if (params.preparation.before.preparedDependencyHash !== params.preparation.after.preparedDependencyHash)
throw new CsoError(
'ASSERTION_FAILED',
'Project-installed test toolchain bytes changed between source phases',
);
}
const transformations = params.manifest.entries.filter((e) => e.transformation),
transformationsHash = sha256(canonical(transformations)),
archivesHash = sha256(canonical([...params.archives].sort())),
requestHash = sha256(canonical(identityRequest)),
preparationHash = params.preparation ? sha256(canonical(params.preparation)) : undefined,
startPlanHash = params.startPlanHash ?? sha256(canonical(request.start)),
testPlanHash =
params.testPlanHash ??
sha256(canonical({ commands: request.existingTests, files: [...request.testFiles].sort() })),
auditPolicyHash = params.auditPolicyHash ?? sha256(canonical({})),
assertionHash = sha256(
canonical({ legitimate: identityRequest.legitimate, security: identityRequest.security }),
),
minimumPassingTests = params.minimumPassingTests ?? request.existingTests.map(() => 1),
runner = {
testToolchain: params.testToolchain,
startPlanHash,
testPlanHash,
commandsHash: sha256(canonical(request.existingTests)),
minimumPassingTestsHash: sha256(canonical(minimumPassingTests)),
};
let assertionAssurance: VerificationManifest['assertionAssurance'], witnessHash: string | undefined;
if (params.witness) {
const beforeReceipt = validateStoredAssertionWitnessReceipt(params.witness.before),
afterReceipt = validateStoredAssertionWitnessReceipt(params.witness.after),
stable = (binding: AssertionWitnessBinding) => {
const { nonce: _, issuedAt: __, expiresAt: ___, ...value } = binding;
return value;
},
expected = (
phase: 'before' | 'after',
sourceHash: string,
dependencyHash: string,
configurationHash: string,
) => ({
schemaVersion: 1,
protocol: 'gstack-cso-assertion-witness-v1',
phase,
runId: params.runId,
findingId: identityRequest.findingId,
policyHash: params.policyHash,
auditPolicyHash,
runtime: {
image: params.runtime.image,
verifierImage: params.verifier.image,
platform: params.runtime.platform,
profile: params.runtime.id,
},
runner,
sourceHash,
dependencyHash,
configurationHash,
requestHash,
patchHash: pHash,
harnessHash,
assertionHash,
fixturesHash,
});
if (
canonical(stable(beforeReceipt.binding)) !==
canonical(
expected('before', params.manifest.executionHash, dependenciesBefore, configurationBefore),
) ||
canonical(stable(afterReceipt.binding)) !==
canonical(expected('after', sourceAfter, dependenciesAfter, configurationAfter)) ||
beforeReceipt.publicKey !== afterReceipt.publicKey ||
beforeReceipt.keyId !== afterReceipt.keyId ||
beforeReceipt.binding.nonce === afterReceipt.binding.nonce
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Authenticated assertion witness receipts do not bind this verification',
);
const beforeObservation = {
...params.before,
existingTests: beforeReceipt.diagnosticTestsPassed,
inputHash: harnessHash,
},
afterObservation = {
...params.after,
existingTests: afterReceipt.diagnosticTestsPassed,
inputHash: harnessHash,
};
if (
beforeReceipt.observationHash !== witnessObservationHash(beforeObservation) ||
afterReceipt.observationHash !== witnessObservationHash(afterObservation) ||
params.before.existingTests !== beforeReceipt.diagnosticTestsPassed ||
params.after.existingTests !== afterReceipt.diagnosticTestsPassed ||
!beforeReceipt.externalAssertionsPassed ||
!afterReceipt.externalAssertionsPassed
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Authenticated assertion witness receipts do not match the verifier observations',
);
const stableExecutions = (receipt: AssertionWitnessReceipt) =>
receipt.executions.map(({ outputHash: _, ...execution }) => execution);
if (canonical(stableExecutions(beforeReceipt)) !== canonical(stableExecutions(afterReceipt)))
throw new CsoError('ASSERTION_FAILED', 'Repair changed the existing-test execution count or outcome');
assertionAssurance = 'authenticated_out_of_process';
witnessHash = assertionWitnessPairHash({ before: beforeReceipt, after: afterReceipt });
}
const passed = mechanical && reviewGate && assertionAssurance === 'authenticated_out_of_process',
preservationUnattested = mechanical && reviewGate && !passed,
createdAt = new Date().toISOString(),
verification: VerificationManifest = {
version: 3,
id: '',
runId: params.runId,
findingId: identityRequest.findingId,
createdAt,
helperAbi: 3,
runtime: { image: params.runtime.image, platform: params.runtime.platform, profile: params.runtime.id },
testToolchain: params.testToolchain,
policyHash: params.policyHash,
auditPolicyHash,
harnessHash,
requestHash,
startPlanHash,
testPlanHash,
fixturesHash,
patchHash: pHash,
originalSourceHash: params.manifest.originalHash,
transformationsHash,
archivesHash,
...(preparationHash ? { preparationHash } : {}),
beforeSourceHash: params.manifest.executionHash,
afterSourceHash: sourceAfter,
beforeDependencies: dependenciesBefore,
afterDependencies: dependenciesAfter,
beforeConfiguration: configurationBefore,
afterConfiguration: configurationAfter,
before: { ...params.before, inputHash: harnessHash },
after: { ...params.after, inputHash: harnessHash },
review: identityRequest.review,
reviewAssurance,
...(assertionAssurance ? { assertionAssurance } : {}),
testCompletionAssurance,
...(witnessHash ? { witnessHash } : {}),
result: passed ? 'runtime_tested' : inconclusive || preservationUnattested ? 'inconclusive' : 'failed',
};
const id = verificationIdentity(verification);
verification.id = id;
if (!['runtime_tested', 'tested'].includes(verification.result)) return { manifest: verification };
const bundle: RepairBundle = {
schemaVersion: 3,
runId: params.runId,
id,
createdAt,
expiresAt: new Date(Date.parse(createdAt) + 30 * 86400_000).toISOString(),
requiredInputs: {
sourceHash: params.manifest.executionHash,
originalHash: params.manifest.originalHash,
runtimeImage: params.runtime.image,
platform: params.runtime.platform,
archives: params.archives,
...(params.dependencyClosures ? { dependencyClosures: params.dependencyClosures } : {}),
},
request: identityRequest,
verification,
transformations,
...(params.preparation ? { preparation: params.preparation } : {}),
...(params.reviewArtifact ? { reviewArtifact: params.reviewArtifact } : {}),
witness: params.witness!,
};
return { manifest: verification, bundle };
}
export function validateRepairBundle(
value: unknown,
id: string,
sourceRoot?: string,
sourceManifest?: SnapshotManifest,
): RepairBundle {
const bundle = value as RepairBundle;
if (
!bundle ||
bundle.schemaVersion !== 3 ||
bundle.id !== id ||
bundle.runId !== bundle.verification?.runId ||
bundle.verification?.id !== id ||
verificationIdentity(bundle.verification) !== id
)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle identity or verification provenance is invalid');
const request = validateVerificationRequest(bundle.request),
verification = bundle.verification,
required = bundle.requiredInputs;
const createdAtMs = Date.parse(bundle.createdAt);
if (
!Number.isFinite(createdAtMs) ||
new Date(createdAtMs).toISOString() !== bundle.createdAt ||
bundle.createdAt !== verification.createdAt ||
bundle.expiresAt !== new Date(createdAtMs + 30 * 86400_000).toISOString()
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle retention timestamps do not match their authenticated verification time',
);
if (
!['runtime_tested', 'tested'].includes(verification.result) ||
!['self_attested', 'host_verified'].includes(verification.reviewAssurance) ||
verification.assertionAssurance !== 'authenticated_out_of_process' ||
(verification.result === 'tested' &&
verification.testCompletionAssurance !== 'authenticated_out_of_process') ||
(verification.result === 'runtime_tested' && verification.testCompletionAssurance !== 'self_reported')
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle lacks the assurance required by its repair label',
);
if (!['runtime', 'project'].includes(verification.testToolchain))
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle test toolchain provenance is invalid');
if (
request.findingId !== verification.findingId ||
request.runtimeProfile !== verification.runtime.profile ||
sha256(canonical(request)) !== verification.requestHash ||
canonical(request.review) !== canonical(verification.review) ||
patchHash(request) !== verification.patchHash ||
![verification.requestHash, verification.startPlanHash, verification.testPlanHash].every((value) =>
/^[a-f0-9]{64}$/.test(value),
) ||
sha256(canonical(request.fixtures)) !== verification.fixturesHash ||
required.sourceHash !== verification.beforeSourceHash ||
required.originalHash !== verification.originalSourceHash ||
required.runtimeImage !== verification.runtime.image ||
required.platform !== verification.runtime.platform ||
sha256(canonical([...(required.archives ?? [])].sort())) !== verification.archivesHash ||
sha256(canonical(bundle.transformations ?? [])) !== verification.transformationsHash
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle request, harness, or contents do not match their authenticated manifest',
);
if (!bundle.witness || !verification.witnessHash)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle omitted its authenticated external assertion witness',
);
const beforeWitness = validateStoredAssertionWitnessReceipt(bundle.witness.before),
afterWitness = validateStoredAssertionWitnessReceipt(bundle.witness.after),
stable = (binding: AssertionWitnessBinding) => {
const { nonce: _, issuedAt: __, expiresAt: ___, ...rest } = binding;
return rest;
},
assertionHash = sha256(canonical({ legitimate: request.legitimate, security: request.security }));
if (
assertionWitnessPairHash({ before: beforeWitness, after: afterWitness }) !== verification.witnessHash ||
beforeWitness.publicKey !== afterWitness.publicKey ||
beforeWitness.keyId !== afterWitness.keyId ||
beforeWitness.binding.nonce === afterWitness.binding.nonce
)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle assertion witness identity is invalid');
for (const [phase, receipt, observation, sourceHash, dependencyHash, configurationHash] of [
[
'before',
beforeWitness,
verification.before,
verification.beforeSourceHash,
verification.beforeDependencies,
verification.beforeConfiguration,
],
[
'after',
afterWitness,
verification.after,
verification.afterSourceHash,
verification.afterDependencies,
verification.afterConfiguration,
],
] as const) {
const binding = stable(receipt.binding);
if (
binding.phase !== phase ||
binding.runId !== verification.runId ||
binding.findingId !== verification.findingId ||
binding.policyHash !== verification.policyHash ||
binding.auditPolicyHash !== verification.auditPolicyHash ||
binding.runtime.image !== verification.runtime.image ||
binding.runtime.verifierImage !== verification.runtime.image ||
binding.runtime.platform !== verification.runtime.platform ||
binding.runtime.profile !== verification.runtime.profile ||
binding.runner.testToolchain !== verification.testToolchain ||
binding.runner.startPlanHash !== verification.startPlanHash ||
binding.runner.testPlanHash !== verification.testPlanHash ||
binding.sourceHash !== sourceHash ||
binding.dependencyHash !== dependencyHash ||
binding.configurationHash !== configurationHash ||
binding.requestHash !== verification.requestHash ||
binding.patchHash !== verification.patchHash ||
binding.harnessHash !== verification.harnessHash ||
binding.assertionHash !== assertionHash ||
binding.fixturesHash !== verification.fixturesHash ||
receipt.observationHash !== witnessObservationHash(observation) ||
receipt.diagnosticTestsPassed !== observation.existingTests ||
!receipt.externalAssertionsPassed
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle assertion witness does not bind its verification manifest',
);
}
if (canonical(beforeWitness.binding.runner) !== canonical(afterWitness.binding.runner))
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle changed the witnessed runner between phases');
if (required.dependencyClosures) {
const hashes = new Set<string>();
for (const phase of ['before', 'after'] as const) {
const closure = required.dependencyClosures[phase] as any;
if (
!closure ||
typeof closure !== 'object' ||
Array.isArray(closure) ||
!Array.isArray(closure.archives) ||
!/^([a-f0-9]{64})$/.test(closure.closureHash ?? '')
)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle dependency closure is malformed');
const { closureHash, ...body } = closure;
if (sha256(canonical(body)) !== closureHash)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle dependency closure identity is invalid');
for (const archive of closure.archives) {
if (!archive || typeof archive !== 'object' || !/^[a-f0-9]{64}$/.test(archive.sha256 ?? ''))
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle dependency archive provenance is malformed',
);
hashes.add(archive.sha256);
}
}
if (canonical([...hashes].sort()) !== canonical([...(required.archives ?? [])].sort()))
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle archive hashes do not match its dependency closures',
);
}
if (required.dependencyClosures && !bundle.preparation)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle omitted prepared-source invariance proofs');
if (verification.testToolchain === 'project' && !bundle.preparation)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle omitted project test-toolchain preparation proofs',
);
if (bundle.preparation) {
if (
!verification.preparationHash ||
sha256(canonical(bundle.preparation)) !== verification.preparationHash ||
canonical(bundle.preparation.before?.transformations) !==
canonical(bundle.preparation.after?.transformations) ||
bundle.preparation.before?.databaseHash !== bundle.preparation.after?.databaseHash
)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle preparation proof is invalid');
for (const phase of ['before', 'after'] as const) {
const proof = bundle.preparation[phase] as PreparationProof,
closure = (required.dependencyClosures as any)?.[phase];
if (
!proof ||
proof.schemaVersion !== 1 ||
![
proof.dependencyClosureHash,
proof.configurationHash,
proof.sourceProjectionHash,
proof.preparedManifestHash,
proof.preparedDependencyHash,
proof.receiptHash,
proof.executionEnvironmentHash,
proof.databaseHash,
].every((value) => /^[a-f0-9]{64}$/.test(value)) ||
!Array.isArray(proof.transformations) ||
proof.transformations.some(
(item) =>
!item ||
typeof item.path !== 'string' ||
!/^[a-f0-9]{64}$/.test(item.sha256) ||
!Number.isInteger(item.mode) ||
typeof item.reason !== 'string',
) ||
(closure && proof.dependencyClosureHash !== closure.closureHash)
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle preparation proof does not bind its dependency closure',
);
}
}
if (
verification.testToolchain === 'project' &&
bundle.preparation!.before.preparedDependencyHash !== bundle.preparation!.after.preparedDependencyHash
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle project test toolchain changed between source phases',
);
if (request.review.artifactId) {
if (!bundle.reviewArtifact)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle omitted its independent review artifact');
validateReviewArtifact(bundle.reviewArtifact, bundle.runId, request);
}
validateVerificationObservation(verification.before);
validateVerificationObservation(verification.after);
if (sourceRoot) {
const references = [
...request.boundaryFiles,
...request.testFiles,
...request.changes.map((change) => change.path),
...request.start.args,
...request.existingTests.flatMap((command) => command.args),
],
hasHandles = references.some((reference) =>
Boolean(
snapshotPathHandleId(reference) ||
(reference.startsWith('./') && snapshotPathHandleId(reference.slice(2))),
),
);
if (hasHandles && !sourceManifest)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Repair bundle path handles require the matching snapshot manifest for source validation',
);
const executionRequest = sourceManifest
? resolveVerificationRequestPaths(sourceManifest, request)
: request;
if (verificationHarnessHash(executionRequest, sourceRoot) !== verification.harnessHash)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle harness does not match supplied source inputs');
const commandsHash = sha256(canonical(executionRequest.existingTests)),
commandHashes = executionRequest.existingTests.map((command) => sha256(canonical(command)));
if (
beforeWitness.binding.runner.commandsHash !== commandsHash ||
canonical(beforeWitness.executions.map((item) => item.commandHash)) !== canonical(commandHashes) ||
canonical(afterWitness.executions.map((item) => item.commandHash)) !== canonical(commandHashes)
)
throw new CsoError('INCOMPATIBLE_INPUT', 'Repair bundle witnessed a different test runner command set');
}
return { ...bundle, request };
}
export class DockerVerificationExecutor implements VerificationExecutor {
private attemptDeadline: number;
private executionStarted = false;
constructor(
private endpoint: DockerEndpoint,
private watchdogPath: string,
private runExecutionDeadline = Date.now() + 300_000,
private onExecutionStarted?: () => void | Promise<void>,
) {
this.attemptDeadline = Math.min(Date.now() + 300_000, runExecutionDeadline);
}
async observe(
source: string,
phase: 'before' | 'after',
request: VerificationRequest,
runtime: QualifiedRuntime,
verifier: QualifiedRuntime,
work: string,
control: string,
execution?: { environment: Record<string, string>; database?: PreparedDatabaseContract },
testEvidence?: { minimumPassingTests: number[] },
witness?: AssertionWitnessHandle,
): Promise<VerificationObservation | WitnessedVerificationResult> {
const phaseDir = secureDirectory(join(work, phase)),
phaseControl = secureDirectory(join(control, phase)),
policy = secureDirectory(join(phaseDir, 'policy')),
policyFile = join(policy, 'verification.json'),
fixtures = secureDirectory(join(phaseDir, 'fixtures'));
const verifierPolicy = JSON.stringify({
phase,
port: request.port,
legitimate: request.legitimate,
security: request.security,
});
if (redact(verifierPolicy) !== verifierPolicy)
throw new CsoError('REDACTION_FAILED', 'Verification harness contains secret-bearing data');
fs.writeFileSync(policyFile, verifierPolicy, { mode: 0o600 });
for (const [path, body] of Object.entries(request.fixtures)) {
const file = containedFile(fixtures, path);
secureDirectory(dirname(file));
fs.writeFileSync(file, body, { mode: 0o600 });
}
const deadline = this.attemptDeadline;
if (deadline <= Date.now())
throw new CsoError('DEADLINE', 'No execution time remains before the reporting reserve');
let group: DockerGroup | undefined;
try {
group = await DockerGroup.create(
this.endpoint,
`${request.findingId.slice(0, 12)}-${phase}-${Date.now()}-${randomBytes(6).toString('hex')}`,
phaseControl,
deadline,
verifier.image,
this.watchdogPath,
);
if (!this.executionStarted) {
this.executionStarted = true;
await this.onExecutionStarted?.();
}
const supplied = execution?.environment ?? {},
allowed = new Set([
'PATH',
'VIRTUAL_ENV',
'PYTHONNOUSERSITE',
'BUNDLE_PATH',
'BUNDLE_FROZEN',
'BUNDLE_DEPLOYMENT',
'BUNDLE_DISABLE_SHARED_GEMS',
'BUNDLE_IGNORE_CONFIG',
'BUNDLE_ALLOW_OFFLINE_INSTALL',
'BUNDLE_CACHE_PATH',
'BUNDLE_USER_HOME',
'GEM_HOME',
'GEM_PATH',
]);
if (
Object.entries(supplied).some(
([key, value]) => !allowed.has(key) || typeof value !== 'string' || value.includes('\0'),
)
)
throw new CsoError('ISOLATION_FAILED', 'Prepared execution environment exceeded its fixed allowlist');
const env = {
...supplied,
PORT: String(request.port),
HOST: '127.0.0.1',
NODE_ENV: 'test',
RAILS_ENV: 'test',
RACK_ENV: 'test',
PYTHONUNBUFFERED: '1',
CI: '1',
SECRET_KEY_BASE: 'cso-synthetic-test-key',
CSO_FIXTURES: '/fixtures',
};
const database = execution?.database;
if (database && runtime.stack !== 'rails')
throw new CsoError('INCOMPATIBLE_INPUT', 'Prepared database contract can only execute with Rails');
if (runtime.stack === 'rails' && !database)
throw new CsoError('PREREQUISITE', 'Rails verification omitted its prepared database contract');
if (database?.adapter === 'postgresql') {
const databaseFile = join(policy, 'postgresql.databases'),
names = database.connections.map((name) => `cso_${name}`);
if (!names.length || names.some((name) => !/^cso_[A-Za-z_][A-Za-z0-9_]{0,47}$/.test(name)))
throw new CsoError('INCOMPATIBLE_INPUT', 'Prepared PostgreSQL connection names are invalid');
fs.writeFileSync(databaseFile, names.join('\n') + '\n', { mode: 0o444, flag: 'wx' });
const postgres = await group.createContainer({
role: 'postgres',
image: database.sidecar.image,
command: ['/opt/cso/run-postgresql', '/policy/postgresql.databases'],
postgresDatabasePolicy: databaseFile,
});
await group.start(postgres);
let ready = false;
for (let attempt = 0; attempt < 100 && !ready; attempt++) {
const checked = await group.execCapture(postgres, [
'/opt/cso/postgresql-ready',
'/policy/postgresql.databases',
]);
ready = checked.code === 0;
if (!ready) await new Promise((resolve) => setTimeout(resolve, 50));
}
if (!ready)
throw new CsoError(
'TOOL_FAILED',
'Disposable PostgreSQL did not create and accept connections for every declared Rails database',
);
}
const cleanCommand = (command: string[]) => [
'/usr/bin/env',
'-i',
...Object.entries(env)
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, value]) => `${key}=${value}`),
...command,
];
const dbPrepare = async (id: string) => {
const result = await group!.execCapture(
id,
cleanCommand(['/usr/local/bin/bundle', 'exec', 'rails', 'db:prepare']),
{ workdir: '/work' },
);
if (result.code !== 0)
throw new CsoError(
'TOOL_FAILED',
'Rails database preparation failed in the isolated test environment',
);
};
let app: string;
if (runtime.stack === 'rails') {
app = await group.createContainer({
role: 'app',
image: runtime.image,
source,
env,
command: ['/opt/cso/run-app', '/bin/sleep', '2147483647'],
readonlyDirectories: [{ host: fixtures, container: '/fixtures' }],
});
await group.start(app);
await dbPrepare(app);
await group.execDetached(app, [request.start.executable, ...request.start.args]);
} else {
app = await group.createContainer({
role: 'app',
image: runtime.image,
source,
env,
command: ['/opt/cso/run-app', request.start.executable, ...request.start.args],
readonlyDirectories: [{ host: fixtures, container: '/fixtures' }],
});
await group.start(app);
}
const verifierId = await group.createContainer({
role: 'verifier',
image: verifier.image,
command: ['/opt/cso/verifier', '/policy/verification.json'],
readonlyFiles: [{ host: policyFile, container: '/policy/verification.json' }],
});
const result = await group.startAttach(verifierId);
let observation: VerificationObservation;
try {
observation = validateVerificationObservation(JSON.parse(result.output.trim()));
} catch {
observation = {
booted: false,
legitimate: false,
security: 'inconclusive',
existingTests: false,
output: 'verifier returned invalid bounded output',
inputHash: '',
};
}
await group.removeContainer(verifierId);
await group.removeContainer(app);
const minimumPassingTests = testEvidence?.minimumPassingTests ?? request.existingTests.map(() => 1);
if (
minimumPassingTests.length !== request.existingTests.length ||
minimumPassingTests.some((value) => !Number.isInteger(value) || value < 1)
)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Helper-derived test execution-count floors do not match the canonical test commands',
);
let existingTests = true;
const executions: Array<{
command: VerificationRequest['existingTests'][number];
code: number;
output: string;
minimumPassingTests: number;
}> = [];
for (const [index, test] of request.existingTests.entries()) {
const rails = runtime.stack === 'rails';
const testId = await group.createContainer({
role: 'tests',
image: runtime.image,
source,
env,
command: rails
? ['/opt/cso/run-app', '/bin/sleep', '2147483647']
: ['/opt/cso/run-app', test.executable, ...test.args],
readonlyDirectories: [{ host: fixtures, container: '/fixtures' }],
});
let testResult: { code: number; output: string };
if (rails) {
await group.start(testId);
await dbPrepare(testId);
const result = await group.execCapture(testId, cleanCommand([test.executable, ...test.args]), {
workdir: '/work',
});
testResult = { code: result.code, output: result.stdout + result.stderr };
} else testResult = await group.startAttach(testId);
executions.push({
command: test,
code: testResult.code,
output: testResult.output,
minimumPassingTests: minimumPassingTests[index],
});
if (!testExecutionPassed(test, testResult.code, testResult.output, minimumPassingTests[index]))
existingTests = false;
await group.removeContainer(testId);
}
if (witness) {
if (observation.existingTests)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'External verifier attempted to assert project test completion',
);
const receipt = await witness.attest(observation, executions),
witnessed = {
...observation,
existingTests: receipt.diagnosticTestsPassed,
inputHash: witness.binding.harnessHash,
};
return { observation: witnessed, witness: receipt };
}
observation.existingTests = existingTests;
return observation;
} finally {
if (group) await group.cleanup();
}
}
}
export async function verifyRepair(params: {
runId: string;
runDir: string;
manifest: SnapshotManifest;
rawRequest: unknown;
runtime: QualifiedRuntime;
verifier: QualifiedRuntime;
policyHash: string;
auditPolicyHash?: string;
archives: string[];
dependencyClosures?: { before: unknown; after: unknown };
preparation?: { before: PreparationProof; after: PreparationProof };
reviewArtifact?: RepairReviewArtifact;
executor: VerificationExecutor;
persist?: boolean;
watchdogPath?: string;
attemptDeadline?: number;
}): Promise<{ manifest: VerificationManifest; bundle: RepairBundle }> {
const identityRequest = validateVerificationRequest(params.rawRequest),
request = resolveVerificationRequestPaths(params.manifest, identityRequest),
snapshot = join(params.runDir, 'snapshot'),
work = join(
params.runDir,
'verification',
`${request.findingId}-${Date.now()}-${randomBytes(4).toString('hex')}`,
),
after = join(work, 'sources', 'after'),
observations = join(work, 'observations'),
groupControls = secureDirectory(join(params.runDir, 'supervision', basename(work), 'docker-groups'));
if (canonical(sanitizeHelperForJson(identityRequest)) !== canonical(identityRequest))
throw new CsoError(
'REDACTION_FAILED',
'Verification request contains sensitive material that cannot enter a replayable bundle',
);
if (!['node', 'bun', 'python', 'rails'].includes(params.runtime.stack))
throw new CsoError('INCOMPATIBLE_INPUT', 'Canonical project tests require an application runtime');
const stack = params.runtime.stack as CsoStack,
beforeTestPlan = assertCanonicalTestPlan(request, snapshot, stack),
beforeStartPlan = assertCanonicalStartPlan(request, snapshot, stack);
if (
beforeTestPlan.toolchain === 'project' &&
request.changes.some((change) => change.effect === 'dependency')
)
throw new CsoError(
'PREREQUISITE',
'Runtime-tested dependency repairs require a test runner pinned in the qualified runtime; project-installed test toolchains may change with the repair',
);
for (const boundary of [
...new Set([...request.boundaryFiles, ...request.testFiles, ...beforeStartPlan.entrypointFiles]),
]) {
const e = params.manifest.entries.find((x) => x.path === boundary);
if (!e || e.transformation)
throw new CsoError(
'INCOMPATIBLE_INPUT',
`Snapshot transformation changes or withholds a verification input: ${boundary}`,
);
}
for (const change of request.changes) {
const path = relativePath(change.path),
entry = params.manifest.entries.find((x) => x.path === path);
containedFile(snapshot, path);
if (change.beforeSha256 === null) {
if (entry)
throw new CsoError(
'INCOMPATIBLE_INPUT',
`Declared new repair path already exists in the snapshot: ${path}`,
);
} else if (!entry || entry.transformation)
throw new CsoError(
'INCOMPATIBLE_INPUT',
`Snapshot transformation changes or withholds a repair input: ${path}`,
);
}
let guardedCleanup: (() => Promise<void>) | undefined;
if (params.watchdogPath) {
const deadline = Math.min(params.attemptDeadline ?? Date.now() + 300_000, Date.now() + 300_000);
guardedCleanup = await attemptGuard(params.runDir, work, params.watchdogPath, deadline);
}
secureDirectory(observations);
let certified: ReturnType<typeof certify> | undefined,
beforeObs: VerificationObservation | undefined,
afterObs: VerificationObservation | undefined,
beforeWitness: AssertionWitnessReceipt | undefined,
afterWitness: AssertionWitnessReceipt | undefined,
failure: unknown,
missingExternalWitness = false;
try {
preparePatchedSource(snapshot, after, request);
const afterTestPlan = canonicalTestPlan(after, stack),
afterStartPlan = canonicalStartPlan(after, stack, request.port);
if (canonical(afterTestPlan) !== canonical(beforeTestPlan))
throw new CsoError(
'ASSERTION_FAILED',
'Repair changed the canonical project test suite, runner configuration, or discovered test inputs',
);
const startShape = (plan: CanonicalStartPlan) => ({
command: plan.command,
kind: plan.kind,
entrypointFiles: plan.entrypointFiles,
}),
changedPaths = new Set(request.changes.map((change) => change.path));
if (
canonical(startShape(afterStartPlan)) !== canonical(startShape(beforeStartPlan)) ||
(afterStartPlan.signature !== beforeStartPlan.signature &&
!beforeStartPlan.entrypointFiles.some((path) => changedPaths.has(path)))
)
throw new CsoError(
'ASSERTION_FAILED',
'Repair changed the helper-derived application startup plan outside its declared patch',
);
const beforeInvariant = treeHash(snapshot),
afterInvariant = treeHash(after);
if (beforeInvariant !== params.manifest.executionHash)
throw new CsoError(
'INCOMPATIBLE_INPUT',
'Retained source does not match the snapshot identity bound to this verification',
);
const testEvidence = { minimumPassingTests: beforeTestPlan.minimumPassingTests },
auditPolicyHash = params.auditPolicyHash ?? sha256(canonical({})),
requestHash = sha256(canonical(identityRequest)),
pHash = patchHash(identityRequest),
harnessHash = verificationHarnessHash(request, snapshot),
assertionHash = sha256(
canonical({ legitimate: identityRequest.legitimate, security: identityRequest.security }),
),
runner = {
testToolchain: beforeTestPlan.toolchain,
startPlanHash: beforeStartPlan.signature,
testPlanHash: beforeTestPlan.signature,
commandsHash: sha256(canonical(request.existingTests)),
minimumPassingTestsHash: sha256(canonical(beforeTestPlan.minimumPassingTests)),
},
session = new AssertionWitnessSession(
observations,
Math.min(params.attemptDeadline ?? Date.now() + 300_000, Date.now() + 300_000),
),
stable = (
phase: 'before' | 'after',
root: string,
sourceHash: string,
): Omit<
AssertionWitnessBinding,
'schemaVersion' | 'protocol' | 'nonce' | 'issuedAt' | 'expiresAt'
> => ({
phase,
runId: params.runId,
findingId: identityRequest.findingId,
policyHash: params.policyHash,
auditPolicyHash,
runtime: {
image: params.runtime.image,
verifierImage: params.verifier.image,
platform: params.runtime.platform,
profile: params.runtime.id,
},
runner,
sourceHash,
dependencyHash: treeHash(root, (p) => DEPENDENCY.test(p)),
configurationHash: treeHash(root, (p) => CONFIG.test(p) && !DEPENDENCY.test(p)),
requestHash,
patchHash: pHash,
harnessHash,
assertionHash,
fixturesHash: sha256(canonical(identityRequest.fixtures)),
}),
beforeHandle = session.handle(stable('before', snapshot, beforeInvariant));
const rawBefore = await params.executor.observe(
snapshot,
'before',
request,
params.runtime,
params.verifier,
observations,
groupControls,
undefined,
testEvidence,
beforeHandle,
),
observedBefore =
'observation' in (rawBefore as any)
? validateVerificationObservation((rawBefore as WitnessedVerificationResult).observation)
: validateVerificationObservation(rawBefore as VerificationObservation);
if ('observation' in (rawBefore as any))
beforeWitness = beforeHandle.validate(
(rawBefore as WitnessedVerificationResult).witness,
observedBefore,
);
if (treeHash(snapshot) !== beforeInvariant)
throw new CsoError('ASSERTION_FAILED', 'Verification mutated the retained source snapshot');
beforeObs = observedBefore;
const afterHandle = session.handle(stable('after', after, afterInvariant)),
rawAfter = await params.executor.observe(
after,
'after',
request,
params.runtime,
params.verifier,
observations,
groupControls,
undefined,
testEvidence,
afterHandle,
),
observedAfter =
'observation' in (rawAfter as any)
? validateVerificationObservation((rawAfter as WitnessedVerificationResult).observation)
: validateVerificationObservation(rawAfter as VerificationObservation);
if ('observation' in (rawAfter as any))
afterWitness = afterHandle.validate((rawAfter as WitnessedVerificationResult).witness, observedAfter);
if (treeHash(after) !== afterInvariant)
throw new CsoError('ASSERTION_FAILED', 'Verification mutated the pristine patched source');
afterObs = observedAfter;
certified = certify({
...params,
request,
identityRequest,
before: beforeObs,
after: afterObs,
beforeRoot: snapshot,
afterRoot: after,
startPlanHash: beforeStartPlan.signature,
testPlanHash: beforeTestPlan.signature,
testToolchain: beforeTestPlan.toolchain,
minimumPassingTests: beforeTestPlan.minimumPassingTests,
...(beforeWitness && afterWitness ? { witness: { before: beforeWitness, after: afterWitness } } : {}),
});
} catch (error) {
failure = error;
}
try {
if (guardedCleanup) await guardedCleanup();
else fs.rmSync(work, { recursive: true, force: true });
} catch (error) {
failure = error;
certified = undefined;
missingExternalWitness = false;
}
if (!failure && certified && !certified.bundle) {
const manifest = certified.manifest,
review = manifest.review;
missingExternalWitness =
!manifest.assertionAssurance &&
manifest.testCompletionAssurance === 'self_reported' &&
manifest.result === 'inconclusive' &&
manifest.before.booted &&
manifest.before.legitimate &&
manifest.before.security === 'intended_failure' &&
manifest.before.existingTests &&
manifest.after.booted &&
manifest.after.legitimate &&
manifest.after.security === 'pass' &&
manifest.after.existingTests &&
review.independent &&
review.rootCauseRepaired &&
review.featurePreserved &&
!review.boundaryMocks;
failure = missingExternalWitness
? new CsoError(
'PREREQUISITE',
'Repair verification retained self-reported project-test diagnostics but requires a helper-authenticated out-of-process external assertion witness before a runtime-tested bundle can be issued',
)
: new CsoError(
'ASSERTION_FAILED',
manifest.result === 'inconclusive'
? 'Repair verification was inconclusive; no repair bundle was issued'
: 'Repair failed one or more required boot, control, security, existing-test, or review assertions; no repair bundle was issued',
);
}
if (failure) {
if (beforeObs) {
const cause =
failure instanceof CsoError
? failure
: new CsoError('ASSERTION_FAILED', 'Repair validation failed after the before-phase observation');
const reproduction = !beforeObs.booted
? 'blocked'
: !beforeObs.legitimate
? 'inconclusive'
: beforeObs.security === 'intended_failure'
? 'reproduced'
: beforeObs.security === 'pass'
? 'disproved'
: 'inconclusive',
harnessHash = verificationHarnessHash(request, snapshot);
const missingWitness =
missingExternalWitness &&
cause.code === 'PREREQUISITE' &&
reproduction === 'reproduced' &&
afterObs?.booted === true &&
afterObs.legitimate === true &&
afterObs.security === 'pass' &&
beforeObs.existingTests &&
afterObs.existingTests;
const raw = {
schemaVersion: 3 as const,
artifactKind: 'repair_candidate' as const,
runId: params.runId,
findingId: identityRequest.findingId,
createdAt: new Date().toISOString(),
bundleIssued: false as const,
runtime: {
image: params.runtime.image,
platform: params.runtime.platform,
profile: params.runtime.id,
},
policyHash: params.policyHash,
requestHash: sha256(canonical(identityRequest)),
harnessHash,
sourceHash: params.manifest.executionHash,
request: identityRequest,
patchHash: patchHash(identityRequest),
testToolchain: beforeTestPlan.toolchain,
testCompletionAssurance: 'self_reported' as const,
...(params.preparation ? { preparationHash: sha256(canonical(params.preparation)) } : {}),
before: { ...beforeObs, inputHash: harnessHash },
...(afterObs ? { after: { ...afterObs, inputHash: harnessHash } } : {}),
reproduction,
repair: missingWitness ? ('proposed' as const) : ('failed' as const),
failure: { code: cause.code, message: cause.message },
},
safe = sanitizeHelperForJson(raw) as Omit<FailedVerificationAttempt, 'id'>,
id = sha256(canonical(safe)).slice(0, 32),
attempt: FailedVerificationAttempt = { ...safe, id };
validateVerificationObservation(attempt.before);
if (attempt.after) validateVerificationObservation(attempt.after);
if (params.persist !== false)
writeJsonExclusive(join(params.runDir, 'verification-attempts', `${id}.json`), attempt);
throw new VerificationAttemptError(cause, attempt);
}
throw failure;
}
if (!certified?.bundle)
throw new CsoError('ASSERTION_FAILED', 'Verification ended without a certifiable result');
if (params.persist !== false) {
const persistable = sanitizeHelperForJson(certified.bundle);
if (canonical(persistable) !== canonical(certified.bundle))
throw new CsoError(
'REDACTION_FAILED',
'Repair bundle provenance contains material that cannot be persisted without changing its identity',
);
validateRepairBundle(persistable, certified.bundle.id, snapshot, params.manifest);
writeJsonExclusive(join(params.runDir, 'bundles', `${certified.bundle.id}.json`), persistable);
}
return { manifest: certified.manifest, bundle: certified.bundle };
}