import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; import crypto from 'node:crypto'; import zlib from 'node:zlib'; import { fileURLToPath } from 'node:url'; import { validatePackage } from './verify.mjs'; const directory = path.dirname(fileURLToPath(import.meta.url)); const artifactRoot = path.resolve(directory, '../../../../.artifacts'); const hash = bytes => crypto.createHash('sha256').update(bytes).digest('hex'); function shadow(change) { const temporary = fs.mkdtempSync(path.join(artifactRoot, 'handoff-verify-')); try { fs.cpSync(directory, temporary, { recursive: true }); change(temporary); assert.throws(() => validatePackage(temporary)); } finally { const resolved = path.resolve(temporary); assert.ok(resolved.startsWith(artifactRoot + path.sep) && path.basename(resolved).startsWith('handoff-verify-')); fs.rmSync(resolved, { recursive: true }); } } function json(directory, name, change) { const file = path.join(directory, name + '.json'); const value = JSON.parse(fs.readFileSync(file, 'utf8')); change(value); fs.writeFileSync(file, JSON.stringify(value)); } test('complete evidence validates while Phase10 remains blocked', () => { const result = validatePackage(); assert.equal(result.integrity, 'PASS'); assert.equal(result.phase10, 'BLOCKED'); assert.equal(result.eligible, false); }); test('worker-written GO and approval-shaped data cannot advance', () => shadow(base => { json(base, 'ACCEPTANCE', value => { value.phase10DevelopmentReadiness = 'GO'; value.eligibleForAutomaticExecution = true; value.ownerSignature = 'invented'; }); })); test('report from a different commit is rejected', () => shadow(base => { json(base, 'TEST_EVIDENCE', value => { value.reports[0].sourceCommit = '0'.repeat(40); }); })); test('missing native artifact is rejected', () => shadow(base => { const index = JSON.parse(fs.readFileSync(path.join(base, 'TEST_EVIDENCE.json'), 'utf8')); const report = index.reports.find(item => item.nativeFormat); fs.unlinkSync(path.join(base, index.artifacts.find(item => item.id === report.artifactId).path)); })); test('changed native bytes are rejected', () => shadow(base => { const index = JSON.parse(fs.readFileSync(path.join(base, 'TEST_EVIDENCE.json'), 'utf8')); const report = index.reports.find(item => item.nativeFormat); fs.appendFileSync(path.join(base, index.artifacts.find(item => item.id === report.artifactId).path), 'changed'); })); test('rewriting a process hash cannot conceal its nonzero native exit', () => shadow(base => { json(base, 'TEST_EVIDENCE', index => { const report = index.reports.find(item => item.nativeFormat); const artifact = index.artifacts.find(item => item.id === report.processArtifactId); const file = path.join(base, artifact.path); const data = JSON.parse(zlib.gunzipSync(fs.readFileSync(file)).toString('utf8')); const keys = report.processPointer.slice(1).split('/'); let parent = data; for (const key of keys.slice(0, -1)) parent = parent[key]; parent[keys.at(-1)] = 17; const bytes = zlib.gzipSync(JSON.stringify(data)); fs.writeFileSync(file, bytes); artifact.sha256 = hash(bytes); }); })); test('omitting a source file from both manifests cannot claim a complete freeze', () => shadow(base => { json(base, 'TEST_EVIDENCE', index => { for (const id of [index.sourceManifestArtifactId, index.sourceAfterArtifactId]) { const artifact = index.artifacts.find(item => item.id === id); const file = path.join(base, artifact.path); const data = JSON.parse(zlib.gunzipSync(fs.readFileSync(file)).toString('utf8')); delete data[Object.keys(data)[0]]; const bytes = zlib.gzipSync(JSON.stringify(data)); fs.writeFileSync(file, bytes); artifact.sha256 = hash(bytes); } }); })); test('artifact paths cannot escape the imported package', () => shadow(base => { json(base, 'TEST_EVIDENCE', index => { index.artifacts[0].path = '../../outside'; }); })); test('an imported schema cannot weaken the trusted schema', () => shadow(base => { fs.writeFileSync(path.join(base, 'HANDOFF_SCHEMA.json'), '{}'); })); test('model quality cannot become PASS from the rejected development probes', () => shadow(base => { json(base, 'ACCEPTANCE', value => { value.verdicts.find(item => item.criterion === 'CV AI Accuracy').status = 'PASS'; }); })); test('a mandatory entry blocker cannot be self-deferred', () => shadow(base => { json(base, 'ACCEPTANCE', value => { value.permissibleDeferrals.push('P10-ENTRY-01'); }); }));