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; database?: PreparedDatabaseContract }, testEvidence?: { minimumPassingTests: number[] }, witness?: AssertionWitnessHandle, ): Promise; } 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> { 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): 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; 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, 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; 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; 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; 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(); 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, ) { 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; database?: PreparedDatabaseContract }, testEvidence?: { minimumPassingTests: number[] }, witness?: AssertionWitnessHandle, ): Promise { 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) | 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 | 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, 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 }; }