/** CSO's versioned, host-independent evidence contract. Runtime claims are helper-owned. */ import { createHash } from 'node:crypto'; export const ABI = 3; export const MAX_OUTPUT = 1024 * 1024; const UNSAFE_STRING_CONTROLS = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/u; const UNSAFE_PROPERTY_CONTROLS = /[\x00-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/u; export type Completeness = 'complete' | 'partial' | 'not assessed'; export type Severity = 'critical' | 'high' | 'medium' | 'low' | 'informational'; export type ErrorCode = | 'INVALID_ARGUMENT' | 'INVALID_SCHEMA' | 'MISSING_INPUT' | 'SNAPSHOT_RACE' | 'UNSAFE_PATH' | 'REDACTION_FAILED' | 'PERSISTENCE_FAILED' | 'TOOL_UNAVAILABLE' | 'TOOL_FAILED' | 'ISOLATION_FAILED' | 'INSUFFICIENT_CAPACITY' | 'DEADLINE' | 'CANCELLED' | 'PREREQUISITE' | 'INCOMPATIBLE_INPUT' | 'ASSERTION_FAILED'; export class CsoError extends Error { constructor( public code: ErrorCode, message: string, ) { super(message); this.name = 'CsoError'; } } export const sha256 = (value: string | Buffer): string => createHash('sha256').update(value).digest('hex'); export const canonical = (value: unknown): string => { if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`; if (value && typeof value === 'object') return `{${Object.keys(value) .sort() .map((k) => `${JSON.stringify(k)}:${canonical((value as any)[k])}`) .join(',')}}`; return JSON.stringify(value); }; export interface CoverageRecord { domain: string; scope: string; status: 'assessed' | 'partial' | 'not_assessed' | 'not_applicable'; method: string; gaps: string[]; exclusions: string[]; evidence: string[]; tool?: { name: string; version: string; freshness: string; outcome: string }; } export interface ApplicationModel { actors: string[]; assets: string[]; entrypoints: string[]; tenantBoundaries: string[]; sensitiveOperations: string[]; invariants: string[]; } export interface FindingV3 { id: string; fingerprint: string; title: string; rootCause: string; location: { path: string; line: number; symbol: string }; advisoryIds: string[]; severity: Severity; confidence: 'high' | 'medium' | 'low'; confidenceRationale: string; evidence: 'supported' | 'hypothesis' | 'legacy_review'; attackerControl: string; impact: string; scenario: string; trace: string[]; references: string[]; recommendation: string; challenge: { reviewer: string; independent: boolean; mode: 'independent_agent' | 'sequential_fallback'; callers: string; controls: string; counterevidence: string; conclusion: string; }; dependency?: { affectedVersion: string; reachability: 'reachable' | 'unreachable' | 'unknown'; exposure: string; exploitation: string; }; reproduction: 'not_attempted' | 'blocked' | 'inconclusive' | 'disproved' | 'reproduced'; repair: 'not_attempted' | 'proposed' | 'failed' | 'runtime_tested' | 'tested'; closure: 'open' | 'resolved' | 'unknown'; verificationId?: string; reproductionAttemptId?: string; verificationAssurance?: { assertions: 'authenticated_out_of_process'; testCompletion: 'self_reported' | 'authenticated_out_of_process'; review: 'self_attested' | 'host_verified'; }; } export interface RunPolicy { mode: 'daily' | 'comprehensive'; scope: string; diff: boolean; base: string; offline: boolean; budgetSeconds: number; maxWorkers: 3; maxRepairs: 3; } export interface RunReportV3 { schemaVersion: 3; runId: string; repoId: string; createdAt: string; deadline: string; status: 'running' | 'finished' | 'interrupted'; completeness: Completeness; policy: RunPolicy; source: { root: string; snapshotHash: string; originalHash: string; baseCommit?: string; transformations?: Array<{ path: string; handling: string }>; }; application: ApplicationModel; coverage: CoverageRecord[]; findings: FindingV3[]; gaps: string[]; events: { at: string; kind: string; message: string }[]; parent?: { runId: string; findingId: string; kind: 'recheck' }; modelUsage?: { source: string; tokens: number; cost?: number }; } export interface SnapshotEntry { path: string; pathId: string; originalHash: string; executionHash?: string; bytes: number; mode: number; transformation?: string; } export interface SnapshotPathIdentity { path: string; pathId: string; } export interface SnapshotManifest { version: 3; createdAt: string; expiresAt: string; root: string; originalHash: string; executionHash: string; entries: SnapshotEntry[]; deletedPaths?: SnapshotPathIdentity[]; headCommit?: string; baseCommit?: string; changedPaths?: string[]; } export interface HttpAssertion { name: string; path: string; method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; headers?: Record; body?: string; expected: { status: number; includes?: string; excludes?: string }; vulnerable?: { status: number; includes?: string; excludes?: string }; } export interface Command { executable: string; args: string[]; } export interface VerificationRequest { findingId: string; runtimeProfile: string; port: number; start: Command; legitimate: HttpAssertion[]; security: HttpAssertion; existingTests: Command[]; fixtures: Record; boundaryFiles: string[]; testFiles: string[]; changes: { path: string; beforeSha256: string | null; after: string | null; effect: 'source' | 'configuration' | 'dependency'; }[]; review: { reviewer: string; independent: boolean; rootCauseRepaired: boolean; featurePreserved: boolean; boundaryMocks: boolean; rationale: string; reviewedPatchHash: string; artifactId?: string; }; } export interface RepairReviewArtifact { schemaVersion: 3; id: string; runId: string; findingId: string; createdAt: string; producer: string; reviewer: string; assurance: 'self_attested' | 'host_verified'; requestHash: string; patchHash: string; rootCauseRepaired: boolean; featurePreserved: boolean; boundaryMocks: boolean; rationale: string; } export interface RecheckEvidenceV3 { kind: 'caller' | 'security_boundary'; path: string; line: number; observation: string; } export interface SubmissionV3 { application?: ApplicationModel; findings?: unknown[]; coverage?: unknown[]; gaps?: string[]; modelUsage?: { source: string; tokens: number; cost?: number }; recheck?: { findingId: string; outcome: 'open' | 'resolved' | 'unknown'; evidence: RecheckEvidenceV3[]; rootCause: string; }; } export interface VerificationObservation { booted: boolean; legitimate: boolean; security: 'pass' | 'intended_failure' | 'inconclusive'; existingTests: boolean; output: string; inputHash: string; } export interface AssertionWitnessBinding { schemaVersion: 1; protocol: 'gstack-cso-assertion-witness-v1'; nonce: string; phase: 'before' | 'after'; issuedAt: string; expiresAt: string; runId: string; findingId: string; policyHash: string; auditPolicyHash: string; runtime: { image: string; verifierImage: string; platform: string; profile: string }; runner: { testToolchain: 'runtime' | 'project'; startPlanHash: string; testPlanHash: string; commandsHash: string; minimumPassingTestsHash: string; }; sourceHash: string; dependencyHash: string; configurationHash: string; requestHash: string; patchHash: string; harnessHash: string; assertionHash: string; fixturesHash: string; } export interface AssertionWitnessReceipt { schemaVersion: 1; binding: AssertionWitnessBinding; keyId: string; publicKey: string; observationHash: string; externalAssertionsPassed: boolean; diagnosticTestsPassed: boolean; executions: Array<{ commandHash: string; exitCode: number; outputHash: string; minimumPassingTests: number; executedTests: number; passingTests: number; reportedPassed: boolean; }>; signature: string; } export interface PreparationProof { schemaVersion: 1; dependencyClosureHash: string; configurationHash: string; sourceProjectionHash: string; preparedManifestHash: string; preparedDependencyHash: string; receiptHash: string; executionEnvironmentHash: string; databaseHash: string; transformations: Array<{ path: string; sha256: string; mode: number; reason: string }>; } export interface VerificationManifest { version: 3; id: string; runId: string; findingId: string; createdAt: string; helperAbi: 3; runtime: { image: string; platform: string; profile: string }; testToolchain: 'runtime' | 'project'; policyHash: string; harnessHash: string; requestHash: string; startPlanHash: string; testPlanHash: string; fixturesHash: string; patchHash: string; auditPolicyHash: string; originalSourceHash: string; transformationsHash: string; archivesHash: string; preparationHash?: string; beforeSourceHash: string; afterSourceHash: string; beforeDependencies: string; afterDependencies: string; beforeConfiguration: string; afterConfiguration: string; before: VerificationObservation; after: VerificationObservation; review: VerificationRequest['review']; reviewAssurance: 'self_attested' | 'host_verified'; assertionAssurance?: 'authenticated_out_of_process'; testCompletionAssurance: 'self_reported' | 'authenticated_out_of_process'; witnessHash?: string; result: 'runtime_tested' | 'tested' | 'failed' | 'inconclusive'; } export interface RepairBundle { schemaVersion: 3; runId: string; id: string; createdAt: string; expiresAt: string; requiredInputs: { sourceHash: string; originalHash: string; runtimeImage: string; platform: string; archives: string[]; dependencyClosures?: { before: unknown; after: unknown }; }; request: VerificationRequest; verification: VerificationManifest; transformations: SnapshotEntry[]; preparation?: { before: PreparationProof; after: PreparationProof }; reviewArtifact?: RepairReviewArtifact; witness?: { before: AssertionWitnessReceipt; after: AssertionWitnessReceipt }; } export function object(value: unknown, name = 'input'): Record { if (!value || typeof value !== 'object' || Array.isArray(value)) throw new CsoError('INVALID_SCHEMA', `${name} must be an object`); return value as Record; } function exact(value: Record, allowed: readonly string[], name: string): void { for (const key of Object.keys(value)) if (!allowed.includes(key)) throw new CsoError('INVALID_SCHEMA', `Unexpected ${name} field: ${key}`); } function boolean(value: unknown, name: string): boolean { if (typeof value !== 'boolean') throw new CsoError('INVALID_SCHEMA', `${name} must be a boolean`); return value; } export function string(value: unknown, name: string, max = 8192): string { if (typeof value !== 'string' || !value.trim() || value.length > max || UNSAFE_STRING_CONTROLS.test(value)) throw new CsoError( 'INVALID_SCHEMA', `${name} must be a nonempty string without unsafe control characters (maximum ${max})`, ); return value; } export function strings(value: unknown, name: string): string[] { if (!Array.isArray(value) || value.length > 1000) throw new CsoError('INVALID_SCHEMA', `${name} must be an array`); return value.map((v, i) => string(v, `${name}[${i}]`)); } export function oneOf(value: unknown, choices: readonly T[], name: string): T { if (!choices.includes(value as T)) throw new CsoError('INVALID_SCHEMA', `${name} must be one of ${choices.join(', ')}`); return value as T; } export function relativePath(value: unknown): string { const p = string(value, 'relative path', 4096); if ( p.startsWith('/') || p.includes('\\') || /^[A-Za-z]:/.test(p) || p.split('/').some((x) => !x || x === '.' || x === '..') || /[\x00-\x1f\x7f]/.test(p) ) throw new CsoError('UNSAFE_PATH', 'Expected a contained relative path'); return p; } const SNAPSHOT_PATH_HANDLE = /^@cso-path\/\/([a-f0-9]{32})$/; export function snapshotPathId(root: string, path: string): string { // Validate the root for callers, but do not salt the opaque identity with its // absolute checkout path. Replay must resolve the same retained path after a // matching source tree is supplied from another checkout. string(root, 'snapshot root', 8192); const relative = relativePath(path); return sha256(canonical({ kind: 'cso-path-v3', path: relative })).slice(0, 32); } export function snapshotPathHandle(pathId: string): string { if (!/^[a-f0-9]{32}$/.test(pathId)) throw new CsoError('INVALID_SCHEMA', 'Snapshot path ID must be 32 lowercase hexadecimal characters'); return `@cso-path//${pathId}`; } export function snapshotPathHandleId(value: unknown): string | undefined { if (typeof value !== 'string') return; return SNAPSHOT_PATH_HANDLE.exec(value)?.[1]; } export function snapshotReference(value: unknown): string { const reference = string(value, 'snapshot path or handle', 4096); return snapshotPathHandleId(reference) ? reference : relativePath(reference); } export function snapshotOriginalIdentity( entries: Array>, deletedPaths: Array> = [], ): string { const present = entries.map((entry) => [entry.path, entry.originalHash, entry.mode]); // Preserve the original no-deletion identity for v3 artifacts already // retained by pre-release builds. Any deletion changes the identity and is // therefore impossible to strip from a manifest without detection. return sha256( canonical( deletedPaths.length ? { entries: present, deletedPaths: deletedPaths.map((item) => item.path).sort() } : present, ), ); } export function rootCauseIdentity(value: string): string { return value.normalize('NFKC').trim().replace(/\s+/g, ' ').toLowerCase(); } function advisoryIdentities(values: string[]): string[] { return [...new Set(values.map((value) => value.normalize('NFKC').trim().toUpperCase()))].sort(); } export function fingerprint(f: Pick): string { // Titles, line shifts, severity, and generated descriptions are deliberately absent. return sha256( canonical({ rootCause: rootCauseIdentity(f.rootCause), path: f.location.path, symbol: f.location.symbol, advisories: advisoryIdentities(f.advisoryIds), }), ).slice(0, 32); } export function validateFinding(input: unknown): FindingV3 { const v = object(input, 'finding'), loc = object(v.location, 'location'), c = object(v.challenge, 'challenge'); for (const reserved of [ 'reproduction', 'repair', 'closure', 'verificationId', 'reproductionAttemptId', 'verificationAssurance', ]) if (reserved in v) throw new CsoError('INVALID_SCHEMA', `${reserved} is helper-owned`); exact( v, [ 'title', 'rootCause', 'location', 'advisoryIds', 'severity', 'confidence', 'confidenceRationale', 'evidence', 'attackerControl', 'impact', 'scenario', 'trace', 'references', 'recommendation', 'challenge', 'dependency', ], 'finding', ); exact(loc, ['path', 'line', 'symbol'], 'location'); exact( c, ['reviewer', 'independent', 'mode', 'callers', 'controls', 'counterevidence', 'conclusion'], 'challenge', ); const f: FindingV3 = { id: '', fingerprint: '', title: string(v.title, 'title'), rootCause: string(v.rootCause, 'rootCause'), location: { path: snapshotReference(loc.path), line: loc.line, symbol: string(loc.symbol, 'symbol') }, advisoryIds: advisoryIdentities(strings(v.advisoryIds ?? [], 'advisoryIds')), severity: oneOf(v.severity, ['critical', 'high', 'medium', 'low', 'informational'], 'severity'), confidence: oneOf(v.confidence, ['high', 'medium', 'low'], 'confidence'), confidenceRationale: string(v.confidenceRationale, 'confidenceRationale'), evidence: oneOf(v.evidence, ['supported', 'hypothesis'], 'evidence'), attackerControl: string(v.attackerControl, 'attackerControl'), impact: string(v.impact, 'impact'), scenario: string(v.scenario, 'scenario'), trace: strings(v.trace, 'trace'), references: strings(v.references, 'references'), recommendation: string(v.recommendation, 'recommendation'), challenge: { reviewer: string(c.reviewer, 'reviewer'), independent: boolean(c.independent, 'challenge.independent'), mode: oneOf(c.mode, ['independent_agent', 'sequential_fallback'], 'challenge.mode'), callers: string(c.callers, 'callers'), controls: string(c.controls, 'controls'), counterevidence: string(c.counterevidence, 'counterevidence'), conclusion: string(c.conclusion, 'conclusion'), }, reproduction: 'not_attempted', repair: 'not_attempted', closure: 'open', }; if (!Number.isInteger(f.location.line) || f.location.line < 1) throw new CsoError('INVALID_SCHEMA', 'line must be a positive integer'); const fallbackLabel = 'sequential challenge; independent agent unavailable'; if ( (f.challenge.independent && (f.challenge.mode !== 'independent_agent' || f.challenge.reviewer === fallbackLabel)) || (!f.challenge.independent && (f.challenge.mode !== 'sequential_fallback' || f.challenge.reviewer !== fallbackLabel)) ) throw new CsoError( 'INVALID_SCHEMA', `Challenge mode must bind either an independent agent or the exact fallback label: ${fallbackLabel}`, ); if (f.evidence === 'supported' && (f.confidence === 'low' || !f.trace.length || !f.references.length)) throw new CsoError( 'INVALID_SCHEMA', 'Supported findings require a challenge, a trace, supporting references, and medium/high confidence', ); if (v.dependency) { const d = object(v.dependency); exact(d, ['affectedVersion', 'reachability', 'exposure', 'exploitation'], 'dependency'); f.dependency = { affectedVersion: string(d.affectedVersion, 'affectedVersion'), reachability: oneOf(d.reachability, ['reachable', 'unreachable', 'unknown'], 'reachability'), exposure: string(d.exposure, 'exposure'), exploitation: string(d.exploitation, 'exploitation'), }; } f.fingerprint = fingerprint(f); f.id = f.fingerprint; return f; } export function validateCoverage(input: unknown): CoverageRecord { const v = object(input, 'coverage'); exact(v, ['domain', 'scope', 'status', 'method', 'gaps', 'exclusions', 'evidence', 'tool'], 'coverage'); const c: CoverageRecord = { domain: string(v.domain, 'domain'), scope: string(v.scope, 'scope'), status: oneOf(v.status, ['assessed', 'partial', 'not_assessed', 'not_applicable'], 'coverage status'), method: string(v.method, 'method'), gaps: strings(v.gaps, 'gaps'), exclusions: strings(v.exclusions, 'exclusions'), evidence: strings(v.evidence, 'evidence'), }; if (c.status === 'assessed' && (c.gaps.length || !c.evidence.length)) throw new CsoError('INVALID_SCHEMA', 'Assessed coverage needs evidence and no outstanding gaps'); if (c.status === 'partial' && (!c.gaps.length || !c.evidence.length)) throw new CsoError('INVALID_SCHEMA', 'Partial coverage needs assessed evidence and a concrete gap'); if (c.status === 'not_assessed' && !c.gaps.length) throw new CsoError('INVALID_SCHEMA', 'Unassessed coverage needs a concrete gap'); if (c.status === 'not_applicable' && (!c.evidence.length || c.gaps.length)) throw new CsoError( 'INVALID_SCHEMA', 'Non-applicability requires evidence and cannot retain an assessment gap', ); if (v.tool) { const t = object(v.tool); exact(t, ['name', 'version', 'freshness', 'outcome'], 'coverage tool'); c.tool = { name: string(t.name, 'tool name'), version: string(t.version, 'tool version'), freshness: string(t.freshness, 'freshness'), outcome: string(t.outcome, 'outcome'), }; } return c; } export function validateCommand(value: unknown, name: string): Command { const v = object(value, name), executable = string(v.executable, `${name}.executable`, 4096), args = strings(v.args ?? [], `${name}.args`); exact(v, ['executable', 'args'], name); if (!executable.startsWith('/') || executable.includes('..')) throw new CsoError('INVALID_SCHEMA', `${name}.executable must be an absolute in-container path`); return { executable, args }; } export function validateVerificationObservation(value: unknown): VerificationObservation { const v = object(value, 'verification observation'); for (const key of Object.keys(v)) if (!['booted', 'legitimate', 'security', 'existingTests', 'output', 'inputHash'].includes(key)) throw new CsoError('INVALID_SCHEMA', `Unexpected verification observation field: ${key}`); if ( typeof v.booted !== 'boolean' || typeof v.legitimate !== 'boolean' || typeof v.existingTests !== 'boolean' ) throw new CsoError('INVALID_SCHEMA', 'Verification observation outcomes must be booleans'); if (typeof v.output !== 'string' || v.output.length > 8192 || v.output.includes('\0')) throw new CsoError('INVALID_SCHEMA', 'Verification observation output must be a bounded string'); if (typeof v.inputHash !== 'string' || (!/^$/.test(v.inputHash) && !/^[a-f0-9]{64}$/.test(v.inputHash))) throw new CsoError('INVALID_SCHEMA', 'Verification observation inputHash must be empty or a sha256 hash'); return { booted: v.booted, legitimate: v.legitimate, security: oneOf( v.security, ['pass', 'intended_failure', 'inconclusive'], 'verification security outcome', ), existingTests: v.existingTests, output: v.output, inputHash: v.inputHash, }; } function assertion(value: unknown, name: string): HttpAssertion { const v = object(value, name), expected = object(v.expected, `${name}.expected`); exact(v, ['name', 'path', 'method', 'headers', 'body', 'expected', 'vulnerable'], name); const oracle = (x: Record, n: string) => { exact(x, ['status', 'includes', 'excludes'], n); if (!Number.isInteger(x.status) || x.status < 100 || x.status > 599) throw new CsoError('INVALID_SCHEMA', `${n}.status must be an HTTP status`); return { status: x.status, ...(x.includes === undefined ? {} : { includes: string(x.includes, `${n}.includes`) }), ...(x.excludes === undefined ? {} : { excludes: string(x.excludes, `${n}.excludes`) }), }; }; const path = string(v.path, `${name}.path`, 4096); if (!path.startsWith('/') || path.startsWith('//') || /[\r\n]/.test(path)) throw new CsoError('INVALID_SCHEMA', `${name}.path must stay on numeric loopback`); const headers: Record = {}; if (v.headers !== undefined) for (const [k, val] of Object.entries(object(v.headers, `${name}.headers`))) { if ( !/^[A-Za-z0-9-]{1,100}$/.test(k) || typeof val !== 'string' || val.length > 8192 || /[\r\n]/.test(val) ) throw new CsoError('INVALID_SCHEMA', `Invalid ${name} header`); headers[k] = val; } return { name: string(v.name, `${name}.name`), path, method: oneOf(v.method, ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], `${name}.method`), ...(Object.keys(headers).length ? { headers } : {}), ...(v.body === undefined ? {} : { body: string(v.body, `${name}.body`, 65536) }), expected: oracle(expected, `${name}.expected`), ...(v.vulnerable === undefined ? {} : { vulnerable: oracle(object(v.vulnerable), `${name}.vulnerable`) }), }; } export function validateVerificationRequest(input: unknown): VerificationRequest { const v = object(input, 'verification request'), changes = v.changes, fixtures = object(v.fixtures ?? {}, 'fixtures'), review = object(v.review, 'review'); exact( v, [ 'findingId', 'runtimeProfile', 'port', 'start', 'legitimate', 'security', 'existingTests', 'fixtures', 'boundaryFiles', 'testFiles', 'changes', 'review', ], 'verification request', ); exact( review, [ 'reviewer', 'independent', 'rootCauseRepaired', 'featurePreserved', 'boundaryMocks', 'rationale', 'reviewedPatchHash', 'artifactId', ], 'review', ); if (!Array.isArray(changes) || !changes.length || changes.length > 100) throw new CsoError('INVALID_SCHEMA', 'changes must contain 1..100 declared patch effects'); const cleanFixtures: Record = {}; for (const [p, body] of Object.entries(fixtures)) { cleanFixtures[relativePath(p)] = string(body, `fixture ${p}`, 1024 * 1024); } const request: VerificationRequest = { findingId: string(v.findingId, 'findingId'), runtimeProfile: string(v.runtimeProfile, 'runtimeProfile', 100), port: v.port, start: validateCommand(v.start, 'start'), legitimate: (Array.isArray(v.legitimate) ? v.legitimate : []).map((x, i) => assertion(x, `legitimate[${i}]`), ), security: assertion(v.security, 'security'), existingTests: (Array.isArray(v.existingTests) ? v.existingTests : []).map((x, i) => validateCommand(x, `existingTests[${i}]`), ), fixtures: cleanFixtures, boundaryFiles: strings(v.boundaryFiles, 'boundaryFiles').map(snapshotReference), testFiles: strings(v.testFiles, 'testFiles').map(snapshotReference), changes: changes.map((raw: any, i: number) => { const x = object(raw, `changes[${i}]`), before = x.beforeSha256; exact(x, ['path', 'beforeSha256', 'after', 'effect'], `changes[${i}]`); if (before !== null && (typeof before !== 'string' || !/^[a-f0-9]{64}$/.test(before))) throw new CsoError('INVALID_SCHEMA', `changes[${i}].beforeSha256 must be a hash or null`); return { path: snapshotReference(x.path), beforeSha256: before, after: x.after === null ? null : string(x.after, `changes[${i}].after`, 1024 * 1024), effect: oneOf(x.effect, ['source', 'configuration', 'dependency'], `changes[${i}].effect`), }; }), review: { reviewer: string(review.reviewer, 'reviewer'), independent: boolean(review.independent, 'review.independent'), rootCauseRepaired: boolean(review.rootCauseRepaired, 'review.rootCauseRepaired'), featurePreserved: boolean(review.featurePreserved, 'review.featurePreserved'), boundaryMocks: boolean(review.boundaryMocks, 'review.boundaryMocks'), rationale: string(review.rationale, 'review rationale'), reviewedPatchHash: string(review.reviewedPatchHash, 'reviewedPatchHash'), ...(review.artifactId === undefined ? {} : { artifactId: string(review.artifactId, 'review artifact ID') }), }, }; if (!/^[a-f0-9]{32}$/.test(request.findingId)) throw new CsoError('INVALID_SCHEMA', 'findingId must be a helper-issued identifier'); if (request.review.artifactId !== undefined && !/^[a-f0-9]{32}$/.test(request.review.artifactId)) throw new CsoError('INVALID_SCHEMA', 'review artifact ID must be a helper-issued identifier'); if (!Number.isInteger(request.port) || request.port < 1024 || request.port > 65535) throw new CsoError('INVALID_SCHEMA', 'port must be 1024..65535'); if ( !request.legitimate.length || !request.security.vulnerable || !request.existingTests.length || !request.boundaryFiles.length || !request.testFiles.length ) throw new CsoError( 'INVALID_SCHEMA', 'Verification needs a legitimate control, distinct before/fixed security oracles, existing tests, immutable test files, and boundary files', ); const secure = request.security.expected, vulnerable = request.security.vulnerable; const mutuallyExclusive = secure.status !== vulnerable.status || (secure.includes !== undefined && vulnerable.excludes !== undefined && secure.includes.includes(vulnerable.excludes)) || (vulnerable.includes !== undefined && secure.excludes !== undefined && vulnerable.includes.includes(secure.excludes)); if (!mutuallyExclusive) throw new CsoError( 'INVALID_SCHEMA', 'The vulnerable and fixed security oracles must be provably mutually exclusive', ); if (new Set(request.changes.map((x) => x.path)).size !== request.changes.length) throw new CsoError('INVALID_SCHEMA', 'Patch paths must be unique'); if ( new Set(request.testFiles).size !== request.testFiles.length || request.changes.some((change) => request.testFiles.includes(change.path)) ) throw new CsoError( 'INVALID_SCHEMA', 'Existing-test source files must be unique and unchanged by the repair', ); if ( request.existingTests.some((command) => /(?:^|\/)(?:true|false|echo|printf|env|sh|bash)$/.test(command.executable), ) ) throw new CsoError( 'INVALID_SCHEMA', 'Generic success or shell commands cannot stand in for a project test suite', ); if ( !request.changes.some( (change) => change.beforeSha256 === null || change.after === null || sha256(change.after) !== change.beforeSha256, ) ) throw new CsoError('INVALID_SCHEMA', 'A tested repair must contain at least one material patch effect'); return request; } export function completeness(report: Pick): Completeness { // Scanner adapters preserve operational outcomes, but scanner output is only // candidate evidence. The corresponding investigation domain decides whether // assessment work remains; an optional tool failure cannot override it. // A successful snapshot is a prerequisite, not security assessment work by // itself. Its helper-owned partial/not-assessed state remains material. const work = report.coverage.filter( (c) => c.status !== 'not_applicable' && !c.domain.startsWith('scanner:') && !(['snapshot-inputs', 'history-inputs'].includes(c.domain) && c.status === 'assessed'), ); if (!report.gaps.length && work.length && work.every((c) => c.status === 'assessed')) return 'complete'; return work.some((c) => c.status === 'assessed' || c.status === 'partial') ? 'partial' : 'not assessed'; } export function renderReport(report: RunReportV3): string { const supported = report.findings.filter((f) => f.evidence === 'supported'); const gaps = [ ...new Set([ ...report.gaps, ...report.coverage.filter((c) => !c.domain.startsWith('scanner:')).flatMap((c) => c.gaps), ]), ]; const transformations = report.source.transformations ?? []; // Report JSON is canonical evidence. Markdown is a safe plain-text view: // collapse line breaks and escape all Markdown control characters so model, // repository, scanner, and advisory strings cannot forge report structure. const plain = (value: unknown): string => String(value) .replace(/[\x00-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]+/gu, ' ') .replace(/\s{2,}/g, ' ') .trim() .replace(/[\\`*_[\]{}()#+!|<>]/g, '\\$&'); const list = (values: string[]): string => (values.length ? values.map(plain).join('; ') : 'none'); const terminal = [...report.events].reverse().find((item) => item.kind === 'terminal'), startedAt = Date.parse(report.createdAt), terminalAt = terminal ? Date.parse(terminal.at) : NaN; const elapsed = Number.isFinite(startedAt) && Number.isFinite(terminalAt) && terminalAt >= startedAt ? `; elapsed ${terminalAt - startedAt} ms` : ''; const timing = `Timing: started ${plain(report.createdAt)}; deadline ${plain(report.deadline)}${terminal ? `; terminal ${plain(terminal.at)}${elapsed}` : ''}.`; const usage = report.modelUsage ? `Model usage: ${report.modelUsage.tokens} host-reported tokens from ${plain(report.modelUsage.source)}${report.modelUsage.cost === undefined ? '' : `; host-reported cost ${report.modelUsage.cost}`}.` : undefined; const findingLines = (f: FindingV3): string[] => [ `- ${plain(f.severity.toUpperCase())} ${plain(f.title)} [${plain(f.id)}]`, ` Location: ${plain(f.location.path)}:${f.location.line} (${plain(f.location.symbol)}). Confidence: ${plain(f.confidence)} — ${plain(f.confidenceRationale)}. Evidence: ${plain(f.evidence)}.`, ` Attacker scenario: ${plain(f.scenario)}`, ` Attacker control: ${plain(f.attackerControl)}. Impact: ${plain(f.impact)}.`, ` Trace: ${list(f.trace)}. Supporting references: ${list(f.references)}.`, ` Counterevidence considered: ${plain(f.challenge.counterevidence)}. Challenge: ${plain(f.challenge.mode)} by ${plain(f.challenge.reviewer)}. Conclusion: ${plain(f.challenge.conclusion)}.`, ` Repair recommendation: ${plain(f.recommendation)}`, ` Reproduction: ${plain(f.reproduction)}${f.reproductionAttemptId ? ` (attempt ${plain(f.reproductionAttemptId)})` : ''}. Repair: ${plain(f.repair)}. Closure: ${plain(f.closure)}.`, ...(f.verificationId ? [ ` Verification: ${plain(f.verificationId)}. Bundle: bundles/${plain(f.verificationId)}.json. Assertion assurance: ${plain(f.verificationAssurance?.assertions ?? 'unknown')}. Test completion assurance: ${plain(f.verificationAssurance?.testCompletion ?? 'unknown')}. Review assurance: ${plain(f.verificationAssurance?.review ?? 'unknown')}.`, ] : []), ]; const model = report.application; return [ `${report.completeness} — ${plain(report.policy.scope)}${report.policy.diff ? ` (diff against ${plain(report.policy.base)})` : ''}`, `Run: ${plain(report.runId)}. Mode: ${plain(report.policy.mode)}.`, timing, ...(usage ? [usage] : []), `Material gaps: ${gaps.length ? list(gaps) : 'none reported'}.`, '', 'Application model:', `- Actors: ${list(model.actors)}.`, `- Assets: ${list(model.assets)}.`, `- Entrypoints: ${list(model.entrypoints)}.`, `- Tenant boundaries: ${list(model.tenantBoundaries)}.`, `- Sensitive operations: ${list(model.sensitiveOperations)}.`, `- Security invariants: ${list(model.invariants)}.`, '', ...(supported.length ? ['Supported findings:', ...supported.flatMap(findingLines)] : ['No supported findings in the assessed scope.']), ...(report.policy.mode === 'comprehensive' ? [ '', 'Hypotheses (unconfirmed):', ...report.findings.filter((f) => f.evidence === 'hypothesis').flatMap(findingLines), ] : []), '', 'Snapshot transformations:', ...(transformations.length ? transformations.map((item) => `- ${plain(item.path)}: ${plain(item.handling)}`) : ['- none']), '', 'Coverage:', ...report.coverage.flatMap((c) => [ `- ${plain(c.domain)}: ${plain(c.status)}; ${plain(c.method)}${c.tool ? `; tool ${plain(c.tool.name)} ${plain(c.tool.version)}, freshness ${plain(c.tool.freshness)}, outcome ${plain(c.tool.outcome)}` : ''}.`, ` Scope: ${plain(c.scope)}. Evidence: ${list(c.evidence)}. Gaps: ${list(c.gaps)}. Exclusions: ${list(c.exclusions)}.`, ]), '', ].join('\n'); } type LegacyJson = null | boolean | number | string | LegacyJson[] | { [key: string]: LegacyJson }; function legacyJson(value: unknown, depth = 0, seen = new WeakSet()): LegacyJson { if (depth > 32) throw new CsoError('INVALID_SCHEMA', 'Legacy report nesting is too deep'); if (value === null || typeof value === 'boolean') return value; if (typeof value === 'number') { if (!Number.isFinite(value)) throw new CsoError('INVALID_SCHEMA', 'Legacy report numbers must be finite'); return value; } if (typeof value === 'string') { if (value.length > MAX_OUTPUT || UNSAFE_STRING_CONTROLS.test(value)) throw new CsoError( 'INVALID_SCHEMA', 'Legacy report strings must be bounded and free of unsafe control characters', ); return value; } if (!value || typeof value !== 'object') throw new CsoError('INVALID_SCHEMA', 'Legacy report contains a non-JSON value'); if (seen.has(value)) throw new CsoError('INVALID_SCHEMA', 'Legacy report cannot be cyclic'); seen.add(value); try { if (Array.isArray(value)) { if (value.length > 10_000) throw new CsoError('INVALID_SCHEMA', 'Legacy report array is too large'); return value.map((item) => legacyJson(item, depth + 1, seen)); } const entries = Object.entries(value as Record); if (entries.length > 10_000) throw new CsoError('INVALID_SCHEMA', 'Legacy report object is too large'); const out: Record = Object.create(null); for (const [key, item] of entries) { if ( key.length > 1024 || ['__proto__', 'prototype', 'constructor'].includes(key) || UNSAFE_PROPERTY_CONTROLS.test(key) ) throw new CsoError('INVALID_SCHEMA', 'Legacy report contains an unsafe property'); out[key] = legacyJson(item, depth + 1, seen); } return out; } finally { seen.delete(value); } } export function importLegacy(input: unknown): { schemaVersion: 2; readOnly: true; findings: any[]; warning: string; } { const v = object(input, 'legacy report'); if ( !Array.isArray(v.findings) || ![2, '2', '2.0', '2.0.0'].includes(v.schemaVersion ?? v.schema_version ?? v.version) ) throw new CsoError('INVALID_SCHEMA', 'Expected a v2 report with findings'); return { schemaVersion: 2, readOnly: true, warning: 'Legacy VERIFIED is review evidence only; it does not establish reproduction, tested repair, or closure.', findings: v.findings.map((raw: any, index: number) => { const f = object(raw, `legacy finding ${index + 1}`); return { title: typeof f.title === 'string' ? string(f.title, 'legacy title') : `Legacy finding ${index + 1}`, status: typeof f.status === 'string' ? string(f.status, 'legacy status') : 'unknown', ...(typeof f.severity === 'string' ? { severity: string(f.severity, 'legacy severity') } : {}), ...(typeof f.description === 'string' ? { description: string(f.description, 'legacy description') } : {}), legacy: legacyJson(f), evidence: 'legacy_review', reproduction: 'not_attempted', repair: 'not_attempted', closure: 'unknown', }; }), }; }