mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-16 18:05:31 +02:00
* feat(cso): add verified audits and replayable repair bundles * fix(cso): harden qualification and setup boundaries * fix(cso): assemble security canaries at runtime * fix(cso): bound release proof and maintenance work Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): require complete evaluation reports Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): replay expired snapshots from supplied source Co-Authored-By: OpenAI Codex <noreply@openai.com> * test(cso): synchronize DNS cancellation assertion Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore(ship): exempt repository owner from liveness proof Co-Authored-By: OpenAI Codex <noreply@openai.com> * test(cso): make recheck retention overlap deterministic Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore: bump version and changelog (v1.85.0.0) Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): pass native release gates Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore: move release to v1.86.0.0 Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): resolve rechecks by finding Co-Authored-By: OpenAI Codex <noreply@openai.com> * chore: move release to v1.87.0.0 Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): pass macOS and Windows release gates Normalize BSD wc output, compare Windows paths by filesystem identity, preserve portable snapshot race coverage, and narrow POSIX-only Windows fixtures. Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix(cso): harden native verification gates * fix(cso): refine Windows native diagnostics * test(cso): isolate Windows Git startup failure * test(cso): stabilize Windows native diagnostics * fix(cso): support hardened Git on Windows * fix(cso): close final verification gaps * test(cso): bound cold Docker fixture setup * fix(cso): restore cross-platform free-suite gates --------- Co-authored-by: OpenAI Codex <noreply@openai.com>
213 lines
65 KiB
TypeScript
213 lines
65 KiB
TypeScript
import { afterEach, describe, expect, spyOn, test } from 'bun:test';
|
|
import * as fs from 'node:fs';
|
|
import * as os from 'node:os';
|
|
import * as path from 'node:path';
|
|
import * as crypto from 'node:crypto';
|
|
import { canonical, completeness, CsoError, fingerprint, importLegacy, renderReport, sha256, snapshotPathHandle, snapshotPathId, validateCoverage, validateFinding, validateVerificationObservation, validateVerificationRequest } from '../lib/cso/contracts';
|
|
import { assertCanonicalStartPlan, canonicalStartPlan, canonicalTestPlan, certify, fileEffect, makeReviewArtifact, patchHash, preparePatchedSource, resolveVerificationRequestPaths, testExecutionPassed, treeHash, validateRepairBundle, validateReviewArtifact, verificationIdentity, verifyRepair } from '../lib/cso/verification';
|
|
import { assertionWitnessPairHash, witnessObservationHash } from '../lib/cso/witness';
|
|
import { admit, machinePoolRoot, markSupervised, release } from '../lib/cso/admission';
|
|
import { sanitizeHelperForJson } from '../lib/cso/process';
|
|
|
|
const dirs:string[]=[];const tmp=()=>{const p=fs.mkdtempSync(path.join(os.tmpdir(),'cso-contract-'));dirs.push(p);return p;};afterEach(()=>{for(const p of dirs.splice(0))fs.rmSync(p,{recursive:true,force:true});});
|
|
const CREDENTIAL_CANARY=['ghp_','abcdefghijklmnopqrstuvwxyz1234567890'].join('');
|
|
const finding:any={title:'Cross-tenant read',rootCause:'Tenant query omits caller tenant predicate',location:{path:'src/users.ts',line:4,symbol:'getUser'},advisoryIds:[],severity:'high',confidence:'high',confidenceRationale:'The captured caller-to-sink trace and control review directly support the finding',evidence:'supported',attackerControl:'Authenticated user selects another object ID',impact:'Reads another tenant record',scenario:'A tenant supplies a known record ID owned by a second tenant and receives that record',trace:['GET /users/:id','getUser','db.user.findUnique'],references:['src/users.ts:4','OWASP API1:2023'],recommendation:'Bind every record lookup to the authenticated tenant identifier and reject a missing tenant context',challenge:{reviewer:'reviewer-2',independent:true,mode:'independent_agent',callers:'Route is public to authenticated tenants',controls:'Session middleware authenticates but does not bind tenant',counterevidence:'UUID is unguessable only by convention',conclusion:'Authorization invariant is absent'}};
|
|
const request=(before:string,after:string)=>({findingId:'a'.repeat(32),runtimeProfile:'node',port:3456,start:{executable:'/usr/local/bin/node',args:['app.js']},legitimate:[{name:'health',path:'/health',method:'GET',expected:{status:200,includes:'ok'}}],security:{name:'tenant isolation',path:'/user?id=2',method:'GET',expected:{status:403},vulnerable:{status:200,includes:'tenant-b'}},existingTests:[{executable:'/usr/local/bin/node',args:['test.js']}],testFiles:['test.js'],fixtures:{'tenant.json':'{}'},boundaryFiles:['app.js'],changes:[{path:'app.js',beforeSha256:sha256(before),after,effect:'source'}],review:{reviewer:'independent-reviewer',independent:true,rootCauseRepaired:true,featurePreserved:true,boundaryMocks:false,rationale:'Predicate now binds the caller tenant and health behavior is preserved',reviewedPatchHash:''}});
|
|
// Structural signed fixture for bundle-reader mutation tests. Production
|
|
// issuance uses AssertionWitnessSession in verifyRepair instead.
|
|
function authenticatedBundleFixture(certified:ReturnType<typeof certify>,params:any,outcomes?:Record<'before'|'after',{executedTests:number;passingTests:number}>):any{
|
|
const verification=structuredClone(certified.manifest),identityRequest=params.identityRequest??params.request,pair=crypto.generateKeyPairSync('ed25519'),publicKey=pair.publicKey.export({format:'der',type:'spki'}).toString('hex'),keyId=sha256(Buffer.from(publicKey,'hex')),createdAt=verification.createdAt,runner={testToolchain:params.testToolchain,startPlanHash:verification.startPlanHash,testPlanHash:verification.testPlanHash,commandsHash:sha256(canonical(params.request.existingTests)),minimumPassingTestsHash:sha256(canonical(params.request.existingTests.map(()=>1)))},make=(phase:'before'|'after')=>{const observation=verification[phase],counts=outcomes?.[phase]??{executedTests:1,passingTests:1},binding:any={schemaVersion:1,protocol:'gstack-cso-assertion-witness-v1',nonce:sha256(`${phase}:${createdAt}`),phase,issuedAt:createdAt,expiresAt:new Date(Date.parse(createdAt)+300_000).toISOString(),runId:params.runId,findingId:identityRequest.findingId,policyHash:verification.policyHash,auditPolicyHash:verification.auditPolicyHash,runtime:{image:params.runtime.image,verifierImage:params.verifier.image,platform:params.runtime.platform,profile:params.runtime.id},runner,sourceHash:phase==='before'?verification.beforeSourceHash:verification.afterSourceHash,dependencyHash:phase==='before'?verification.beforeDependencies:verification.afterDependencies,configurationHash:phase==='before'?verification.beforeConfiguration:verification.afterConfiguration,requestHash:verification.requestHash,patchHash:verification.patchHash,harnessHash:verification.harnessHash,assertionHash:sha256(canonical({legitimate:identityRequest.legitimate,security:identityRequest.security})),fixturesHash:verification.fixturesHash},executions=params.request.existingTests.map((command:any)=>({commandHash:sha256(canonical(command)),exitCode:0,outputHash:sha256(`structural signed fixture ${phase}`),minimumPassingTests:1,...counts,reportedPassed:counts.passingTests>=1})),unsigned:any={schemaVersion:1,binding,keyId,publicKey,observationHash:witnessObservationHash(observation),externalAssertionsPassed:true,diagnosticTestsPassed:executions.every((execution:any)=>execution.reportedPassed),executions};return{...unsigned,signature:crypto.sign(null,Buffer.from(canonical(unsigned)),pair.privateKey).toString('hex')}};const witness={before:make('before'),after:make('after')};verification.assertionAssurance='authenticated_out_of_process';verification.testCompletionAssurance='self_reported';verification.witnessHash=assertionWitnessPairHash(witness);verification.result='runtime_tested';verification.id='';const id=verificationIdentity(verification);verification.id=id;
|
|
return{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.manifest.entries.filter((entry:any)=>entry.transformation),...(params.preparation?{preparation:params.preparation}:{}),witness};
|
|
}
|
|
|
|
describe('CSO evidence contracts',()=>{
|
|
test('stable fingerprints normalize root-cause whitespace and advisory identity while ignoring generated prose',()=>{const a=validateFinding({...finding,advisoryIds:['ghsa-abcd-1234-efgh','CVE-2026-12345']}),b=validateFinding({...finding,title:'Different words',severity:'medium',confidence:'medium',scenario:'Different scenario prose',recommendation:'Different repair prose',rootCause:' TENANT query\n omits caller tenant predicate ',advisoryIds:['cve-2026-12345','GHSA-ABCD-1234-EFGH','cve-2026-12345'],location:{...finding.location,line:99}});expect(a.fingerprint).toBe(b.fingerprint);expect(b.advisoryIds).toEqual(['CVE-2026-12345','GHSA-ABCD-1234-EFGH']);});
|
|
test('model output cannot set proof or closure states',()=>{expect(()=>validateFinding({...finding,reproduction:'reproduced'})).toThrow('helper-owned');expect(()=>validateFinding({...finding,repair:'tested'})).toThrow('helper-owned');expect(()=>validateFinding({...finding,closure:'resolved'})).toThrow('helper-owned');expect(()=>validateFinding({...finding,verificationAssurance:{assertions:'authenticated_out_of_process',testCompletion:'authenticated_out_of_process',review:'self_attested'}})).toThrow('helper-owned');});
|
|
test('opaque snapshot handles resolve to exact private verification paths and command arguments',()=>{const root='/private/repository',appId=snapshotPathId(root,'src/private.js'),testId=snapshotPathId(root,'test/control.js'),appHandle=snapshotPathHandle(appId),testHandle=snapshotPathHandle(testId),raw:any=request('vulnerable\n','fixed\n');raw.start.args=[appHandle];raw.existingTests[0].args=[`./${testHandle}`];raw.boundaryFiles=[appHandle];raw.testFiles=[testHandle];raw.changes[0].path=appHandle;raw.review.reviewedPatchHash=patchHash(raw);const publicRequest=validateVerificationRequest(raw),manifest:any={root,entries:[{path:'src/private.js',pathId:appId},{path:'test/control.js',pathId:testId}]},resolved=resolveVerificationRequestPaths(manifest,publicRequest);expect(publicRequest.start.args).toEqual([appHandle]);expect(publicRequest.existingTests[0].args).toEqual([`./${testHandle}`]);expect(publicRequest.boundaryFiles[0]).toBe(appHandle);expect(resolved.start.args).toEqual(['src/private.js']);expect(resolved.existingTests[0].args).toEqual(['./test/control.js']);expect(resolved.boundaryFiles).toEqual(['src/private.js']);expect(resolved.testFiles).toEqual(['test/control.js']);expect(resolved.changes[0].path).toBe('src/private.js');expect(resolved.review.reviewedPatchHash).toBe(patchHash(publicRequest));});
|
|
test('supported evidence needs references, a repair, a challenge, a trace, and calibrated confidence',()=>{expect(()=>validateFinding({...finding,trace:[]})).toThrow();expect(()=>validateFinding({...finding,references:[]})).toThrow('supporting references');expect(()=>validateFinding({...finding,confidence:'low'})).toThrow();expect(()=>validateFinding({...finding,challenge:{...finding.challenge,independent:false}})).toThrow('fallback label');expect(()=>validateFinding({...finding,challenge:{...finding.challenge,reviewer:'sequential challenge; independent agent unavailable'}})).toThrow('fallback label');const fallback=validateFinding({...finding,challenge:{...finding.challenge,reviewer:'sequential challenge; independent agent unavailable',independent:false,mode:'sequential_fallback'}});expect(fallback.challenge).toMatchObject({independent:false,mode:'sequential_fallback'});const missing=structuredClone(finding);delete missing.challenge.independent;expect(()=>validateFinding(missing)).toThrow('must be a boolean');});
|
|
test('every incomplete coverage state names its gap',()=>{expect(()=>validateCoverage({domain:'auth',scope:'all',status:'assessed',method:'trace',gaps:['admin not read'],exclusions:[],evidence:['route']})).toThrow();expect(()=>validateCoverage({domain:'auth',scope:'all',status:'partial',method:'trace',gaps:[],exclusions:[],evidence:['route']})).toThrow('concrete gap');expect(()=>validateCoverage({domain:'auth',scope:'all',status:'not_assessed',method:'trace',gaps:[],exclusions:[],evidence:[]})).toThrow('concrete gap');expect(()=>validateCoverage({domain:'payments',scope:'all',status:'not_applicable',method:'model',gaps:[],exclusions:[],evidence:[]})).toThrow();});
|
|
test('completeness is independent of findings and renders the required empty phrase',()=>{const base:any={coverage:[{domain:'auth',scope:'all',status:'assessed',method:'trace',gaps:[],exclusions:[],evidence:['routes']}],gaps:[]};expect(completeness(base)).toBe('complete');const report:any={...base,schemaVersion:3,runId:'r',repoId:'x',createdAt:'2026-01-01',deadline:'2026-01-01',status:'finished',completeness:'complete',policy:{mode:'daily',scope:'all',diff:false,base:'main',offline:true,budgetSeconds:600,maxWorkers:3,maxRepairs:3},source:{root:'/x',snapshotHash:'s',originalHash:'o'},application:{actors:[],assets:[],entrypoints:[],tenantBoundaries:[],sensitiveOperations:[],invariants:[]},findings:[],events:[]};expect(renderReport(report)).toContain('No supported findings in the assessed scope.');base.gaps=['scanner failed'];expect(completeness(base)).toBe('partial');});
|
|
test('readable reports show timing and supplied host model usage without inventing either',()=>{const base:any={schemaVersion:3,runId:'r',repoId:'x',createdAt:'2026-01-01T00:00:00.000Z',deadline:'2026-01-01T00:10:00.000Z',status:'finished',completeness:'complete',policy:{mode:'daily',scope:'all',diff:false,base:'main',offline:true,budgetSeconds:600,maxWorkers:3,maxRepairs:3},source:{root:'/x',snapshotHash:'s',originalHash:'o'},application:{actors:[],assets:[],entrypoints:[],tenantBoundaries:[],sensitiveOperations:[],invariants:[]},coverage:[{domain:'auth',scope:'all',status:'assessed',method:'trace',gaps:[],exclusions:[],evidence:['routes']}],findings:[],gaps:[],events:[{at:'2026-01-01T00:01:05.500Z',kind:'terminal',message:'finished'}]};const markdown=renderReport({...base,modelUsage:{source:'host api',tokens:1234,cost:0.25}});expect(markdown).toContain('Timing: started 2026-01-01T00:00:00.000Z; deadline 2026-01-01T00:10:00.000Z; terminal 2026-01-01T00:01:05.500Z; elapsed 65500 ms.');expect(markdown).toContain('Model usage: 1234 host-reported tokens from host api; host-reported cost 0.25.');expect(renderReport(base)).not.toContain('Model usage:');});
|
|
test('readable reports include substantiating detail and explicit proof assurances',()=>{const supported=validateFinding({...finding,title:'Cross tenant\n# FORGED SECTION',scenario:'Caller sends `id`\n- forged bullet'});supported.repair='tested';supported.verificationId='a'.repeat(32);supported.verificationAssurance={assertions:'authenticated_out_of_process',testCompletion:'authenticated_out_of_process',review:'self_attested'};const report:any={schemaVersion:3,runId:'run',repoId:'repo',createdAt:'2026-01-01',deadline:'2026-01-01',status:'finished',completeness:'complete',policy:{mode:'daily',scope:'auth',diff:false,base:'main',offline:true,budgetSeconds:600,maxWorkers:3,maxRepairs:3},source:{root:'/x',snapshotHash:'s',originalHash:'o'},application:{actors:['tenant user'],assets:['records'],entrypoints:['GET /users/:id'],tenantBoundaries:['tenant_id'],sensitiveOperations:['read'],invariants:['tenant isolation']},coverage:[{domain:'auth',scope:'all',status:'assessed',method:'caller trace',gaps:[],exclusions:[],evidence:['src/users.ts:4']}],findings:[supported],gaps:[],events:[]},markdown=renderReport(report);expect(markdown).toContain('Application model:');expect(markdown).toContain('Attacker scenario:');expect(markdown).toContain('Supporting references:');expect(markdown).toContain('Repair recommendation:');expect(markdown).toContain(`Bundle: bundles/${'a'.repeat(32)}.json. Assertion assurance: authenticated\\_out\\_of\\_process. Test completion assurance: authenticated\\_out\\_of\\_process. Review assurance: self\\_attested.`);expect(markdown).not.toContain('\n# FORGED SECTION');expect(markdown).not.toContain('\n- forged bullet');});
|
|
test('readable reports reject and strip bidirectional or terminal control forgery',()=>{expect(()=>validateFinding({...finding,title:'Safe \u202e [HIGH forged]'})).toThrow('unsafe control characters');const supported=validateFinding(finding);supported.title='Safe \u202e [HIGH forged] \u0085';const report:any={schemaVersion:3,runId:'run',repoId:'repo',createdAt:'2026-01-01',deadline:'2026-01-01',status:'finished',completeness:'complete',policy:{mode:'daily',scope:'auth',diff:false,base:'main',offline:true,budgetSeconds:600,maxWorkers:3,maxRepairs:3},source:{root:'/x',snapshotHash:'s',originalHash:'o'},application:{actors:[],assets:[],entrypoints:[],tenantBoundaries:[],sensitiveOperations:[],invariants:[]},coverage:[{domain:'auth',scope:'all',status:'assessed',method:'trace',gaps:[],exclusions:[],evidence:['route']}],findings:[supported],gaps:[],events:[]},markdown=renderReport(report);expect(markdown).not.toMatch(/[\u202e\u0085]/u);expect(markdown).toContain('Safe \\[HIGH forged\\]');});
|
|
test('optional scanner failure is operational evidence, not a second assessment domain',()=>{const report:any={coverage:[{domain:'dependencies',scope:'all',status:'assessed',method:'manual reachability analysis',gaps:[],exclusions:[],evidence:['lock and callers']},{domain:'scanner:osv',scope:'all',status:'not_assessed',method:'qualified scanner',gaps:['catalog unavailable'],exclusions:[],evidence:[],tool:{name:'osv',version:'unavailable',freshness:'unknown',outcome:'not_assessed'}}],gaps:[]};expect(completeness(report)).toBe('complete');});
|
|
test('v2 VERIFIED imports as readable legacy evidence, never proof',()=>{const original={status:'VERIFIED',title:'old',fingerprint:'legacy-fingerprint',location:{path:'src/old.ts',line:7},impact:'historical impact',recommendation:'historical repair',repair:'VERIFIED'};const v=importLegacy({schemaVersion:2,findings:[original]});expect(v.readOnly).toBe(true);expect(v.findings[0]).toMatchObject({evidence:'legacy_review',reproduction:'not_attempted',repair:'not_attempted',closure:'unknown',legacy:original});});
|
|
test('legacy reports reject display controls in preserved values and property names',()=>{for(const finding of [{status:'OPEN',title:'old',nested:{value:'line\u2028forgery'}},{status:'OPEN',title:'old',nested:{['severity\u202eHIGH']:'forged'}}])expect(()=>importLegacy({schemaVersion:2,findings:[finding]})).toThrow(/unsafe (?:control characters|property)/);});
|
|
test('Docker admission is machine-wide and supervised slots survive owner deadlines until cleanup',()=>{const endpoint=`unix:///tmp/cso-${process.pid}-${Date.now()}.sock`,old=process.env.GSTACK_HOME,a=admit(endpoint,'a',Date.now()-1);markSupervised(a);process.env.GSTACK_HOME=tmp();const b=admit(endpoint,'b',Date.now()+60_000);try{expect(()=>admit(endpoint,'c',Date.now()+60_000)).toThrow('Two reproduction groups');}finally{release(a);release(b);if(old===undefined)delete process.env.GSTACK_HOME;else process.env.GSTACK_HOME=old;}});
|
|
test('wallet-shaped random lease capabilities remain byte-identical protocol metadata',()=>{const endpoint=`unix:///tmp/cso-wallet-token-${process.pid}-${Date.now()}.sock`,token='1abcdefabcdefabcdefabcdefabcdefa',random=crypto.randomBytes,patched=spyOn(crypto,'randomBytes').mockImplementation(((size:number)=>size===16?Buffer.from(token,'hex'):random(size)) as typeof crypto.randomBytes);let lease:ReturnType<typeof admit>|undefined;try{lease=admit(endpoint,'wallet-token',Date.now()+60_000);expect(lease.token).toBe(token);expect(JSON.parse(fs.readFileSync(path.join(lease.path,'lease.json'),'utf8')).token).toBe(token);expect(fs.readFileSync(path.join(lease.path,'lease.token'),'utf8').trim()).toBe(token);markSupervised(lease);expect(JSON.parse(fs.readFileSync(path.join(lease.path,'lease.json'),'utf8')).token).toBe(token);}finally{patched.mockRestore();if(lease)release(lease);}});
|
|
test('a paused initializer cannot have its incomplete slot reclaimed or overwritten',()=>{
|
|
const endpoint=`unix:///tmp/cso-initializer-${process.pid}-${Date.now()}.sock`,pool=path.join(machinePoolRoot(),sha256(endpoint).slice(0,24)),slot0=path.join(pool,'slot-0'),originalMkdir=fs.mkdirSync;
|
|
let paused=false,contender:ReturnType<typeof admit>|undefined;
|
|
const mkdir=spyOn(fs,'mkdirSync').mockImplementation(((target:fs.PathLike,options?:fs.MakeDirectoryOptions & {recursive?:false})=>{
|
|
const result=originalMkdir(target,options as any);
|
|
if(!paused&&String(target)===slot0){paused=true;const old=new Date(Date.now()-60_000);fs.utimesSync(slot0,old,old);contender=admit(endpoint,'contender',Date.now()+60_000);}
|
|
return result;
|
|
}) as typeof fs.mkdirSync);
|
|
let initializer:ReturnType<typeof admit>|undefined;try{initializer=admit(endpoint,'initializer',Date.now()+60_000);}finally{mkdir.mockRestore();}
|
|
expect(paused).toBe(true);expect(initializer!.slot).toBe(0);expect(contender!.slot).toBe(1);expect(initializer!.token).not.toBe(contender!.token);
|
|
for(const lease of [initializer!,contender!]){expect(JSON.parse(fs.readFileSync(path.join(lease.path,'lease.json'),'utf8')).token).toBe(lease.token);expect(fs.readFileSync(path.join(lease.path,'lease.token'),'utf8').trim()).toBe(lease.token);expect(fs.readdirSync(path.join(pool,`.slot-${lease.slot}.control`))).toEqual([]);}
|
|
try{expect(()=>admit(endpoint,'third',Date.now()+60_000)).toThrow('Two reproduction groups');}finally{release(initializer!);release(contender!);}
|
|
});
|
|
test('a fully published recovery claim remains owned while its initializer is paused',()=>{
|
|
const endpoint=`unix:///tmp/cso-claim-publish-${process.pid}-${Date.now()}.sock`,pool=path.join(machinePoolRoot(),sha256(endpoint).slice(0,24)),claim=path.join(pool,'.slot-0.control','.recovery'),originalMkdir=fs.mkdirSync,originalUnlink=fs.unlinkSync;
|
|
let paused=false,contender:ReturnType<typeof admit>|undefined;
|
|
const contend=()=>{paused=true;const old=new Date(Date.now()-60_000);fs.utimesSync(claim,old,old);contender=admit(endpoint,'claim-contender',Date.now()+60_000);};
|
|
// The mkdir hook reproduces the former directory claim's empty publication
|
|
// window. The unlink hook pauses the replacement protocol immediately after
|
|
// its complete temp inode has been atomically published.
|
|
const mkdir=spyOn(fs,'mkdirSync').mockImplementation(((target:fs.PathLike,options?:fs.MakeDirectoryOptions & {recursive?:false})=>{const result=originalMkdir(target,options as any);if(!paused&&String(target)===claim)contend();return result;}) as typeof fs.mkdirSync);
|
|
const unlink=spyOn(fs,'unlinkSync').mockImplementation(((target:fs.PathLike)=>{const result=originalUnlink(target);if(!paused&&String(target).startsWith(`${claim}.tmp.`))contend();return result;}) as typeof fs.unlinkSync);
|
|
let initializer:ReturnType<typeof admit>|undefined;try{initializer=admit(endpoint,'claim-initializer',Date.now()+60_000);}finally{unlink.mockRestore();mkdir.mockRestore();}
|
|
expect(paused).toBe(true);expect(initializer!.slot).toBe(0);expect(contender!.slot).toBe(1);try{release(initializer!);release(contender!);}catch(error){throw error;}
|
|
});
|
|
test('a crashed initializer claim and partial slot are recovered exactly',()=>{
|
|
const endpoint=`unix:///tmp/cso-initializer-crash-${process.pid}-${Date.now()}.sock`,pool=path.join(machinePoolRoot(),sha256(endpoint).slice(0,24)),control=path.join(pool,'.slot-0.control'),claim=path.join(control,'.recovery'),slot=path.join(pool,'slot-0');
|
|
fs.mkdirSync(pool,{mode:0o700});fs.mkdirSync(control,{mode:0o700});fs.writeFileSync(claim,JSON.stringify({pid:2147483647,processIdentity:'linux:1',token:'7'.repeat(32),createdAt:1}),{mode:0o600});fs.mkdirSync(slot,{mode:0o700});const old=new Date(Date.now()-60_000);fs.utimesSync(slot,old,old);
|
|
const recovered=admit(endpoint,'recovered',Date.now()+60_000);try{expect(recovered.slot).toBe(0);expect(JSON.parse(fs.readFileSync(path.join(slot,'lease.json'),'utf8')).token).toBe(recovered.token);expect(fs.readdirSync(control)).toEqual([]);expect(fs.readdirSync(pool).some(name=>name.includes('.stale-'))).toBe(false);}finally{release(recovered);}
|
|
});
|
|
test('admission recovers only the exact no-replace claim link of a dead publisher',()=>{
|
|
const endpoint=`unix:///tmp/cso-claim-hardlink-${process.pid}-${Date.now()}.sock`,pool=path.join(machinePoolRoot(),sha256(endpoint).slice(0,24)),control=path.join(pool,'.slot-0.control'),claim=path.join(control,'.recovery'),temporary=`${claim}.tmp.2147483647.deadbeef`;
|
|
fs.mkdirSync(pool,{mode:0o700});fs.mkdirSync(control,{mode:0o700});fs.writeFileSync(claim,JSON.stringify({pid:2147483647,processIdentity:'linux:1',token:'6'.repeat(32),createdAt:1})+'\n',{mode:0o600});fs.linkSync(claim,temporary);
|
|
const recovered=admit(endpoint,'hardlink-recovered',Date.now()+60_000);try{expect(recovered.slot).toBe(0);expect(fs.readdirSync(control)).toEqual([]);}finally{release(recovered);fs.rmSync(pool,{recursive:true,force:true});}
|
|
});
|
|
test('admission fails closed when a claim temp names a different publisher',()=>{
|
|
const endpoint=`unix:///tmp/cso-claim-mismatch-${process.pid}-${Date.now()}.sock`,pool=path.join(machinePoolRoot(),sha256(endpoint).slice(0,24)),control=path.join(pool,'.slot-0.control'),claim=path.join(control,'.recovery'),temporary=`${claim}.tmp.2147483646.cafebabe`;
|
|
fs.mkdirSync(pool,{mode:0o700});fs.mkdirSync(control,{mode:0o700});fs.writeFileSync(claim,JSON.stringify({pid:2147483647,processIdentity:'linux:1',token:'5'.repeat(32),createdAt:1})+'\n',{mode:0o600});fs.linkSync(claim,temporary);
|
|
try{expect(()=>admit(endpoint,'must-not-admit',Date.now()+60_000)).toThrow('invalid');expect(fs.statSync(claim).nlink).toBe(2);}finally{fs.rmSync(pool,{recursive:true,force:true});}
|
|
});
|
|
test('admission recovery never steals a replacement lease and exact release rejects changed ownership',()=>{
|
|
const endpoint=`unix:///tmp/cso-recovery-${process.pid}-${Date.now()}.sock`,pool=path.join(machinePoolRoot(),sha256(endpoint).slice(0,24));fs.mkdirSync(pool,{mode:0o700});
|
|
const lease=(slot:number,runId:string,token:string,ownerPid:number,supervised:boolean)=>({endpoint,slot,path:path.join(pool,`slot-${slot}`),runId,ownerPid,expiresAt:Date.now()+60_000,token,supervised});
|
|
const publish=(value:ReturnType<typeof lease>)=>{fs.mkdirSync(value.path,{mode:0o700});fs.writeFileSync(path.join(value.path,'lease.json'),JSON.stringify(value),{mode:0o600});fs.writeFileSync(path.join(value.path,'lease.token'),value.token+'\n',{mode:0o600});};
|
|
const stale=lease(0,'stale','8'.repeat(32),2147483647,false),replacement=lease(0,'replacement','9'.repeat(32),process.pid,true),other=lease(1,'other','a'.repeat(32),process.pid,true);publish(stale);publish(other);
|
|
const originalLink=fs.linkSync,originalRename=fs.renameSync;let barrier=false,thirdCode='',canonicalMoves=0,displaced='';
|
|
const rename=spyOn(fs,'renameSync').mockImplementation(((from:fs.PathLike,to:fs.PathLike)=>{if(String(from)===stale.path)canonicalMoves++;return originalRename(from,to);}) as typeof fs.renameSync);
|
|
const link=spyOn(fs,'linkSync').mockImplementation(((from:fs.PathLike,to:fs.PathLike)=>{const result=originalLink(from,to);if(!barrier&&String(to)===path.join(stale.path,'.recovery')){barrier=true;displaced=`${stale.path}.displaced`;originalRename(stale.path,displaced);publish(replacement);fs.writeFileSync(String(from),'publisher-temp-placeholder',{mode:0o600,flag:'wx'});try{admit(endpoint,'third',Date.now()+60_000);}catch(error:any){thirdCode=error?.code??'';}}return result;}) as typeof fs.linkSync);
|
|
try{expect(()=>admit(endpoint,'recoverer',Date.now()+60_000)).toThrow();}finally{link.mockRestore();rename.mockRestore();}
|
|
expect(barrier).toBe(true);expect(thirdCode).toBe('INSUFFICIENT_CAPACITY');expect(canonicalMoves).toBe(0);expect(JSON.parse(fs.readFileSync(path.join(replacement.path,'lease.json'),'utf8')).token).toBe(replacement.token);expect(fs.existsSync(path.join(replacement.path,'.recovery'))).toBe(false);
|
|
fs.writeFileSync(path.join(replacement.path,'lease.token'),'b'.repeat(32)+'\n',{mode:0o600});expect(()=>release(replacement)).toThrow('ownership changed');expect(fs.existsSync(replacement.path)).toBe(true);fs.writeFileSync(path.join(replacement.path,'lease.token'),replacement.token+'\n',{mode:0o600});release(replacement);release(other);if(displaced)fs.rmSync(displaced,{recursive:true,force:true});
|
|
});
|
|
});
|
|
|
|
describe('tested repair certificate gate',()=>{
|
|
test('canonical plans bind test infrastructure and run every Rails suite',()=>{
|
|
const root=tmp();
|
|
fs.writeFileSync(path.join(root,'package.json'),JSON.stringify({scripts:{test:'jest'}}));
|
|
fs.mkdirSync(path.join(root,'tests','fixtures'),{recursive:true});
|
|
fs.writeFileSync(path.join(root,'tests','app.test.js'),'test("ok",()=>{})');
|
|
fs.writeFileSync(path.join(root,'tests','fixtures','account.json'),'{}');
|
|
fs.writeFileSync(path.join(root,'jest.config.js'),'module.exports={}');
|
|
fs.writeFileSync(path.join(root,'app.js'),'server.listen(process.env.PORT)');
|
|
const node=canonicalTestPlan(root,'node');
|
|
expect(node.files).toEqual(['jest.config.js','tests/app.test.js','tests/fixtures/account.json']);
|
|
expect(node.commands).toEqual([{executable:'/work/node_modules/.bin/jest',args:['--runTestsByPath','--passWithNoTests=false','--json','./tests/app.test.js']}]);
|
|
expect(canonicalStartPlan(root,'node',3456).command).toEqual({executable:'/usr/local/bin/node',args:['app.js']});
|
|
expect(()=>assertCanonicalStartPlan({...request('vulnerable\n','fixed\n'),start:{executable:'/usr/local/bin/python',args:['-m','http.server']}} as any,root,'node')).toThrow('helper-derived');
|
|
|
|
const bunRoot=tmp();
|
|
fs.writeFileSync(path.join(bunRoot,'package.json'),JSON.stringify({scripts:{start:'bun app.js',test:'bun test'}}));
|
|
fs.writeFileSync(path.join(bunRoot,'app.js'),'Bun.serve({fetch(){return new Response("ok")}})');
|
|
fs.writeFileSync(path.join(bunRoot,'app.test.js'),'import {test} from "bun:test"; test("ok",()=>{});');
|
|
const bunPolicy=['--no-install','--config=/opt/cso/no-auto-install.toml'];
|
|
expect(canonicalTestPlan(bunRoot,'bun').commands).toEqual([{executable:'/usr/local/bin/bun',args:[...bunPolicy,'test','./app.test.js']}]);
|
|
expect(canonicalStartPlan(bunRoot,'bun',3456).command).toEqual({executable:'/usr/local/bin/bun',args:[...bunPolicy,'app.js']});
|
|
|
|
const python=tmp();fs.mkdirSync(path.join(python,'tests'));
|
|
fs.writeFileSync(path.join(python,'conftest.py'),'import pytest\n');
|
|
fs.writeFileSync(path.join(python,'tests','test_app.py'),'def test_ok():\n assert True\n');
|
|
const pythonArgs=canonicalTestPlan(python,'python').commands[0].args;
|
|
expect(pythonArgs.slice(0,3)).toEqual(['-I','-S','-c']);expect(pythonArgs[3]).toContain('import pytest;sys.path.insert');expect(pythonArgs.slice(4)).toEqual(['-q','--color=no','--','./tests/test_app.py']);
|
|
|
|
const rails=tmp();fs.mkdirSync(path.join(rails,'spec','support'),{recursive:true});fs.mkdirSync(path.join(rails,'test','fixtures'),{recursive:true});
|
|
fs.writeFileSync(path.join(rails,'spec','app_spec.rb'),'RSpec.describe("app") {}');
|
|
fs.writeFileSync(path.join(rails,'spec','support','auth.rb'),'module Auth; end');
|
|
fs.writeFileSync(path.join(rails,'test','app_test.rb'),'class AppTest < ActiveSupport::TestCase; end');
|
|
fs.writeFileSync(path.join(rails,'test','fixtures','users.yml'),'one: {}');
|
|
const plan=canonicalTestPlan(rails,'rails');
|
|
expect(plan.commands.map(command=>command.args)).toEqual([['exec','rspec','--format','json','--','./spec/app_spec.rb'],['exec','rails','test','--no-color','./test/app_test.rb']]);
|
|
expect(plan.files).toContain('spec/support/auth.rb');expect(plan.files).toContain('test/fixtures/users.yml');
|
|
});
|
|
test('ambiguous Python discovery cannot certify an empty unittest run',()=>{const root=tmp();fs.mkdirSync(path.join(root,'tests'));fs.writeFileSync(path.join(root,'tests','test_app.py'),'value = 1\n');expect(()=>canonicalTestPlan(root,'python')).toThrow('ambiguous');});
|
|
test('self-reported in-process test success is inconclusive and cannot mint a repair bundle',()=>{const root=tmp(),before=path.join(root,'before'),after=path.join(root,'after');fs.mkdirSync(before);fs.writeFileSync(path.join(before,'app.js'),'vulnerable\n');fs.writeFileSync(path.join(before,'test.js'),'pass\n');const raw:any=request('vulnerable\n','fixed\n');raw.findingId='1abcdefabcdefabcdefabcdefabcdefa';raw.review.reviewedPatchHash=patchHash(raw);const req=validateVerificationRequest(raw);preparePatchedSource(before,after,req);const params:any={runId:'run',manifest:{version:3,createdAt:'',expiresAt:'',root:'/x',headCommit:'a'.repeat(40),originalHash:'o',executionHash:tree(before),entries:[{path:'app.js',originalHash:sha256('vulnerable\n'),executionHash:sha256('vulnerable\n'),bytes:11,mode:0o600}]},request:req,runtime:{id:'node',image:'r@sha256:'+'a'.repeat(64),platform:'linux/amd64'},verifier:{image:'r@sha256:'+'a'.repeat(64)},before:{booted:true,legitimate:true,security:'intended_failure',existingTests:true,output:'forged runner success',inputHash:''},after:{booted:true,legitimate:true,security:'pass',existingTests:true,output:'forged runner success',inputHash:''},beforeRoot:before,afterRoot:after,policyHash:'p',archives:[],testToolchain:'runtime'};const certified=certify(params);expect(certified.manifest).toMatchObject({findingId:raw.findingId,result:'inconclusive',reviewAssurance:'self_attested',testToolchain:'runtime',testCompletionAssurance:'self_reported'});expect(certified.bundle).toBeUndefined();params.before.existingTests=false;let failed=certify(params);expect(failed.manifest.result).toBe('failed');expect(failed.bundle).toBeUndefined();params.before.existingTests=true;params.after.existingTests=false;failed=certify(params);expect(failed.manifest.result).toBe('failed');expect(failed.bundle).toBeUndefined();params.after.existingTests=true;params.request.review.boundaryMocks=true;failed=certify(params);expect(failed.manifest.result).toBe('failed');expect(failed.bundle).toBeUndefined();});
|
|
test('changed oracle cannot be represented because one request binds before and after',()=>{const raw:any=request('vulnerable\n','fixed\n');raw.security.vulnerable=undefined;expect(()=>validateVerificationRequest(raw)).toThrow();});
|
|
test('verification review booleans and schema fields are explicit',()=>{const missing:any=request('vulnerable\n','fixed\n');missing.review.reviewedPatchHash='pending';delete missing.review.boundaryMocks;expect(()=>validateVerificationRequest(missing)).toThrow('must be a boolean');const typo:any=request('vulnerable\n','fixed\n');typo.review.reviewedPatchHash='pending';typo.review.boundaryMock=false;expect(()=>validateVerificationRequest(typo)).toThrow('Unexpected review field');const extra:any=request('vulnerable\n','fixed\n');extra.review.reviewedPatchHash='pending';extra.security.expected.untrusted='yes';expect(()=>validateVerificationRequest(extra)).toThrow('Unexpected security.expected field');});
|
|
test('a generic successful command cannot impersonate relevant existing tests',()=>{const raw:any=request('vulnerable\n','fixed\n');raw.review.reviewedPatchHash='pending';raw.existingTests=[{executable:'/bin/true',args:['README.md']}];raw.testFiles=['README.md'];expect(()=>validateVerificationRequest(raw)).toThrow('Generic success');});
|
|
test('canonical package tests execute the exact direct runner and reject wrappers or lifecycle mutation',()=>{
|
|
const node=tmp();fs.writeFileSync(path.join(node,'package.json'),JSON.stringify({scripts:{test:'node --test'}}));fs.writeFileSync(path.join(node,'app.test.js'),'test("ok",()=>{})');expect(canonicalTestPlan(node,'node').commands).toEqual([{executable:'/usr/local/bin/node',args:['--test','--test-reporter=tap','./app.test.js']}]);
|
|
const hooked=tmp();fs.writeFileSync(path.join(hooked,'package.json'),JSON.stringify({scripts:{pretest:'rm -rf tests',test:'node --test'}}));fs.writeFileSync(path.join(hooked,'app.test.js'),'test("must run",()=>{})');expect(()=>canonicalTestPlan(hooked,'node')).toThrow('lifecycle hooks');
|
|
const bunJest=tmp();fs.writeFileSync(path.join(bunJest,'package.json'),JSON.stringify({scripts:{test:'jest'}}));fs.writeFileSync(path.join(bunJest,'app.test.js'),'test("must run",()=>{})');expect(canonicalTestPlan(bunJest,'bun').commands).toEqual([{executable:'/work/node_modules/.bin/jest',args:['--runTestsByPath','--passWithNoTests=false','--json','./app.test.js']}]);
|
|
const bunHooked=tmp();fs.writeFileSync(path.join(bunHooked,'package.json'),JSON.stringify({scripts:{test:'bun test',posttest:'rm -rf tests'}}));fs.writeFileSync(path.join(bunHooked,'app.test.js'),'import {test} from "bun:test"; test("must run",()=>{});');expect(()=>canonicalTestPlan(bunHooked,'bun')).toThrow('lifecycle hooks');
|
|
const mismatched=tmp();fs.writeFileSync(path.join(mismatched,'package.json'),JSON.stringify({scripts:{test:'bun test'}}));fs.writeFileSync(path.join(mismatched,'app.test.js'),'test("must run",()=>{})');expect(()=>canonicalTestPlan(mismatched,'node')).toThrow('cannot depend on the Bun test runtime');
|
|
for(const script of ['node tools/run-tests.js','node --test --test-name-pattern=NO_MATCH','tap']){const root=tmp();fs.writeFileSync(path.join(root,'package.json'),JSON.stringify({scripts:{test:script}}));fs.writeFileSync(path.join(root,'app.test.js'),'test("fails",()=>{throw Error("must run")})');expect(()=>canonicalTestPlan(root,'node')).toThrow('recognized direct standard runner');}
|
|
});
|
|
test('canonical starts bypass package lifecycles',()=>{
|
|
const root=tmp();fs.writeFileSync(path.join(root,'package.json'),JSON.stringify({scripts:{start:'node app.js',test:'node --test'}}));fs.writeFileSync(path.join(root,'app.js'),'server.listen(3456)');fs.writeFileSync(path.join(root,'app.test.js'),'test("ok",()=>{})');expect(canonicalStartPlan(root,'node',3456).command).toEqual({executable:'/usr/local/bin/node',args:['app.js']});
|
|
fs.writeFileSync(path.join(root,'package.json'),JSON.stringify({scripts:{prestart:'node rewrite-app.js',start:'node app.js',test:'node --test'}}));expect(()=>canonicalStartPlan(root,'node',3456)).toThrow('lifecycle hooks');
|
|
});
|
|
test('every canonical runner requires unredacted positive passing-test count evidence',()=>{
|
|
const pytestRoot=tmp();fs.mkdirSync(path.join(pytestRoot,'tests'));fs.writeFileSync(path.join(pytestRoot,'tests','test_app.py'),'def test_ok():\n assert True\n');const pytest=canonicalTestPlan(pytestRoot,'python').commands[0];
|
|
const unittestRoot=tmp();fs.mkdirSync(path.join(unittestRoot,'tests'));fs.writeFileSync(path.join(unittestRoot,'tests','test_app.py'),'import unittest\nclass T(unittest.TestCase):\n def test_ok(self): pass\n');const unittest=canonicalTestPlan(unittestRoot,'python').commands[0];
|
|
const cases:Array<{name:string;command:any;positive:string;multiple:string;zero:string}>=[
|
|
{name:'node',command:{executable:'/usr/local/bin/node',args:['--test','--test-reporter=tap','./app.test.js']},positive:'TAP version 13\n# Subtest: named assertion\nok 1 - named assertion\n1..1\n# tests 1\n# pass 1\n# fail 0\n# cancelled 0\n',multiple:'TAP version 13\n# Subtest: first assertion\nok 1 - first assertion\n# Subtest: second assertion\nok 2 - second assertion\n1..2\n# tests 2\n# pass 2\n# fail 0\n# cancelled 0\n',zero:'TAP version 13\n# Subtest: /work/app.test.js\nok 1 - /work/app.test.js\n1..1\n# tests 1\n# pass 1\n# fail 0\n# cancelled 0\n'},
|
|
{name:'bun',command:{executable:'/usr/local/bin/bun',args:['--no-install','test','./app.test.js']},positive:' 1 pass\n 0 fail\nRan 1 test across 1 file.\n',multiple:' 2 pass\n 0 fail\nRan 2 tests across 1 file.\n',zero:' 0 pass\n 0 fail\n 1 skip\nRan 1 test across 1 file.\n'},
|
|
{name:'jest',command:{executable:'/work/node_modules/.bin/jest',args:['--runTestsByPath','--passWithNoTests=false','--json','./app.test.js']},positive:JSON.stringify({success:true,numPassedTests:1,numFailedTests:0,numRuntimeErrorTestSuites:0,numTotalTests:1}),multiple:JSON.stringify({success:true,numPassedTests:2,numFailedTests:0,numRuntimeErrorTestSuites:0,numTotalTests:2}),zero:JSON.stringify({success:true,numPassedTests:0,numFailedTests:0,numRuntimeErrorTestSuites:0,numTotalTests:1})},
|
|
{name:'vitest',command:{executable:'/work/node_modules/.bin/vitest',args:['run','--passWithNoTests=false','--reporter=verbose','./app.test.js']},positive:' Tests 1 passed (1)\n',multiple:' Tests 2 passed (2)\n',zero:' Tests 1 skipped (1)\n'},
|
|
{name:'mocha',command:{executable:'/work/node_modules/.bin/mocha',args:['--fail-zero','--no-dry-run','--forbid-only','--reporter','json','./test/app.test.js']},positive:JSON.stringify({stats:{tests:1,passes:1,pending:0,failures:0}}),multiple:JSON.stringify({stats:{tests:2,passes:2,pending:0,failures:0}}),zero:JSON.stringify({stats:{tests:1,passes:0,pending:1,failures:0}})},
|
|
{name:'ava',command:{executable:'/work/node_modules/.bin/ava',args:['--tap','./test/app.test.js']},positive:'TAP version 13\n# tests 1\n# pass 1\n# fail 0\n',multiple:'TAP version 13\n# tests 2\n# pass 2\n# fail 0\n',zero:'TAP version 13\n# tests 1\n# pass 0\n# fail 0\n'},
|
|
{name:'pytest',command:pytest,positive:'1 passed in 0.01s\n',multiple:'2 passed in 0.01s\n',zero:'1 skipped in 0.01s\n'},
|
|
{name:'unittest',command:unittest,positive:'Ran 1 test in 0.001s\n\nOK\n',multiple:'Ran 2 tests in 0.001s\n\nOK\n',zero:'Ran 1 test in 0.001s\n\nOK (skipped=1)\n'},
|
|
{name:'rspec',command:{executable:'/usr/local/bin/bundle',args:['exec','rspec','--format','json','--','./spec/app_spec.rb']},positive:JSON.stringify({summary:{example_count:1,pending_count:0,failure_count:0,errors_outside_of_examples_count:0}}),multiple:JSON.stringify({summary:{example_count:2,pending_count:0,failure_count:0,errors_outside_of_examples_count:0}}),zero:JSON.stringify({summary:{example_count:1,pending_count:1,failure_count:0,errors_outside_of_examples_count:0}})},
|
|
{name:'rails',command:{executable:'/usr/local/bin/bundle',args:['exec','rails','test','--no-color','./test/app_test.rb']},positive:'1 runs, 0 assertions, 0 failures, 0 errors, 0 skips\n',multiple:'2 runs, 0 assertions, 0 failures, 0 errors, 0 skips\n',zero:'1 runs, 0 assertions, 0 failures, 0 errors, 1 skips\n'},
|
|
];
|
|
for(const item of cases){expect(testExecutionPassed(item.command,0,item.positive),`${item.name} positive output`).toBe(true);expect(testExecutionPassed(item.command,0,item.positive,2),`${item.name} must reject a result below the helper-derived floor`).toBe(false);expect(testExecutionPassed(item.command,0,item.multiple,2),`${item.name} must accept a result meeting the helper-derived floor`).toBe(true);for(const output of [item.zero,'','custom reporter output','[sensitive process output redacted]'])expect(testExecutionPassed(item.command,0,output),`${item.name} must reject missing/zero/redacted counts`).toBe(false);expect(testExecutionPassed(item.command,1,item.positive),`${item.name} nonzero exit`).toBe(false);}
|
|
const node=cases[0];expect(testExecutionPassed(node.command,0,node.positive,2),'Node must meet the statically derived registration floor').toBe(false);expect(testExecutionPassed(node.command,0,`${node.positive}# Subtest: /work/app.test.js\nok 2 - /work/app.test.js\n`),'Node path-wrapper success remains evidence of an early exit even when another named test passed').toBe(false);
|
|
});
|
|
test('a repair cannot turn existing tests into skips and retain a runtime-tested label',()=>{
|
|
const root=tmp(),before=path.join(root,'before'),after=path.join(root,'after');fs.mkdirSync(before);fs.writeFileSync(path.join(before,'app.js'),'vulnerable\n');fs.writeFileSync(path.join(before,'test.js'),'two registered tests\n');const raw:any=request('vulnerable\n','fixed\n');raw.review.reviewedPatchHash=patchHash(raw);const req=validateVerificationRequest(raw);preparePatchedSource(before,after,req);
|
|
const params:any={runId:'run',manifest:{originalHash:'d'.repeat(64),executionHash:treeHash(before),entries:[]},request:req,runtime:{id:'node',image:'runtime@sha256:'+'a'.repeat(64),platform:'linux/amd64'},verifier:{image:'runtime@sha256:'+'a'.repeat(64)},before:{booted:true,legitimate:true,security:'intended_failure',existingTests:true,output:'before',inputHash:''},after:{booted:true,legitimate:true,security:'pass',existingTests:true,output:'after',inputHash:''},beforeRoot:before,afterRoot:after,policyHash:'c'.repeat(64),auditPolicyHash:'e'.repeat(64),archives:[],testToolchain:'runtime'},unsigned=certify(params),witness=authenticatedBundleFixture(unsigned,params,{before:{executedTests:2,passingTests:2},after:{executedTests:2,passingTests:1}}).witness;
|
|
expect(()=>certify({...params,witness})).toThrow('existing-test execution count or outcome');
|
|
});
|
|
test('canonical Python starts use direct prepared launchers and reject root framework shadows',()=>{
|
|
const pin=(name:string)=>`${name}==1.0.0 --hash=sha256:${'a'.repeat(64)}\n`;
|
|
const flask=tmp();fs.writeFileSync(path.join(flask,'requirements.txt'),pin('Flask'));fs.writeFileSync(path.join(flask,'app.py'),'from flask import Flask\napp = Flask(__name__)\n');const flaskCommand=canonicalStartPlan(flask,'python',3456).command;expect(flaskCommand.executable).toBe('/work/.venv/bin/python');expect(flaskCommand.args.slice(0,3)).toEqual(['-I','-S','-c']);expect(flaskCommand.args[3]).toContain('from flask.cli import main');expect(flaskCommand.args.slice(4)).toEqual(['--app','app:app','run','--host','127.0.0.1','--port','3456']);fs.writeFileSync(path.join(flask,'flask.py'),'raise RuntimeError("shadow")\n');expect(()=>canonicalStartPlan(flask,'python',3456)).toThrow('root import shadow');
|
|
const fastapi=tmp();fs.writeFileSync(path.join(fastapi,'requirements.txt'),pin('fastapi')+pin('uvicorn'));fs.writeFileSync(path.join(fastapi,'main.py'),'from fastapi import FastAPI\napp = FastAPI()\n');const fastapiCommand=canonicalStartPlan(fastapi,'python',3456).command;expect(fastapiCommand.executable).toBe('/work/.venv/bin/python');expect(fastapiCommand.args.slice(0,3)).toEqual(['-I','-S','-c']);expect(fastapiCommand.args[3]).toContain('from uvicorn.main import main');expect(fastapiCommand.args.slice(4)).toEqual(['main:app','--app-dir','/work','--host','127.0.0.1','--port','3456']);fs.mkdirSync(path.join(fastapi,'uvicorn'));expect(()=>canonicalStartPlan(fastapi,'python',3456)).toThrow('root import shadow');
|
|
const django=tmp();fs.writeFileSync(path.join(django,'requirements.txt'),pin('Django'));fs.writeFileSync(path.join(django,'manage.py'),'from django.core.management import execute_from_command_line\n');const djangoCommand=canonicalStartPlan(django,'python',3456).command;expect(djangoCommand.executable).toBe('/work/.venv/bin/python');expect(djangoCommand.args.slice(0,3)).toEqual(['-I','-S','-c']);expect(djangoCommand.args[3]).toContain("runpy.run_path('manage.py'");expect(djangoCommand.args.slice(4)).toEqual(['runserver','127.0.0.1:3456','--noreload']);fs.writeFileSync(path.join(django,'django.py'),'raise RuntimeError("shadow")\n');expect(()=>canonicalStartPlan(django,'python',3456)).toThrow('root import shadow');
|
|
});
|
|
test('empty-dependency Python applications use one isolated conventional entrypoint',()=>{const python=tmp();fs.writeFileSync(path.join(python,'requirements.txt'),'');fs.writeFileSync(path.join(python,'app.py'),"from http.server import HTTPServer,BaseHTTPRequestHandler\nHTTPServer(('127.0.0.1',3456),BaseHTTPRequestHandler).serve_forever()\n");fs.mkdirSync(path.join(python,'tests'));fs.writeFileSync(path.join(python,'tests','test_app.py'),'import unittest\nclass TestApp(unittest.TestCase):\n def test_control(self): self.assertTrue(True)\n');expect(canonicalTestPlan(python,'python').toolchain).toBe('runtime');expect(canonicalStartPlan(python,'python',3456)).toMatchObject({kind:'isolated standard-library Python application',command:{executable:'/usr/local/bin/python',args:['-I','app.py']},entrypointFiles:['app.py']});fs.writeFileSync(path.join(python,'server.py'),'print("ambiguous")\n');expect(()=>canonicalStartPlan(python,'python',3456)).toThrow('ambiguous');});
|
|
test('official Python and RSpec configs are immutable and no-execution controls are rejected',()=>{
|
|
const python=tmp();fs.mkdirSync(path.join(python,'tests'));fs.writeFileSync(path.join(python,'tests','test_app.py'),'def test_ok():\n assert True\n');fs.writeFileSync(path.join(python,'.pytest.ini'),'[pytest]\naddopts = --collect-only\n');expect(()=>canonicalTestPlan(python,'python')).toThrow('collect only');
|
|
fs.writeFileSync(path.join(python,'.pytest.ini'),'[pytest]\n');expect(canonicalTestPlan(python,'python').files).toContain('.pytest.ini');fs.writeFileSync(path.join(python,'.pytest.toml'),'[pytest]\n');expect(canonicalTestPlan(python,'python').files).toContain('.pytest.toml');
|
|
const rails=tmp();fs.mkdirSync(path.join(rails,'spec'));fs.writeFileSync(path.join(rails,'spec','app_spec.rb'),'RSpec.describe("app") { it("works") {} }');fs.writeFileSync(path.join(rails,'.rspec-local'),'--dry-run\n');expect(()=>canonicalTestPlan(rails,'rails')).toThrow('dry-run');fs.writeFileSync(path.join(rails,'.rspec-local'),'--format progress\n');expect(canonicalTestPlan(rails,'rails').files).toContain('.rspec-local');
|
|
});
|
|
test('dependency repairs cannot swap a project-installed test runner',async()=>{
|
|
const runDir=tmp(),snapshot=path.join(runDir,'snapshot');fs.mkdirSync(snapshot);const files:Record<string,string>={'package.json':JSON.stringify({scripts:{test:'jest'}}),'package-lock.json':'{}\n','app.js':'server.listen(3456)\n','app.test.js':'test("ok",()=>{})\n'};for(const [name,body] of Object.entries(files))fs.writeFileSync(path.join(snapshot,name),body);const plan=canonicalTestPlan(snapshot,'node'),raw:any=request(files['app.js'],'server.listen(3456)\n');raw.start={executable:'/usr/local/bin/node',args:['app.js']};raw.existingTests=plan.commands;raw.testFiles=plan.files;raw.changes=[{path:'package-lock.json',beforeSha256:sha256(files['package-lock.json']),after:'{"changed":true}\n',effect:'dependency'}];raw.review.reviewedPatchHash=patchHash(raw);const entries=Object.entries(files).map(([path,body])=>({path,originalHash:sha256(body),executionHash:sha256(body),bytes:Buffer.byteLength(body),mode:0o600})),manifest:any={version:3,createdAt:'2026-01-01T00:00:00Z',expiresAt:'2026-01-08T00:00:00Z',root:'/repo',headCommit:'a'.repeat(40),originalHash:'b'.repeat(64),executionHash:treeHash(snapshot),entries};let executed=false;await expect(verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime:{id:'node',stack:'node',image:'runtime@sha256:'+'a'.repeat(64),platform:'linux/amd64'} as any,verifier:{id:'node',stack:'node',image:'runtime@sha256:'+'a'.repeat(64),platform:'linux/amd64'} as any,policyHash:'c'.repeat(64),archives:[],executor:{observe:async()=>{executed=true;throw new Error('must not run');}},persist:false})).rejects.toMatchObject({code:'PREREQUISITE'});expect(executed).toBe(false);
|
|
});
|
|
test('overlapping security oracles and no-op repairs cannot be certified',()=>{const overlapping:any=request('vulnerable\n','fixed\n');overlapping.review.reviewedPatchHash='pending';overlapping.security.vulnerable={...overlapping.security.expected};expect(()=>validateVerificationRequest(overlapping)).toThrow('mutually exclusive');const noop:any=request('vulnerable\n','vulnerable\n');noop.review.reviewedPatchHash='pending';expect(()=>validateVerificationRequest(noop)).toThrow('material patch');});
|
|
test('review is a separate content-bound but explicitly self-attested artifact',()=>{const raw:any=request('vulnerable\n','fixed\n');raw.review.reviewedPatchHash=patchHash(raw);const req=validateVerificationRequest(raw),artifact=makeReviewArtifact('run',req,'producer-session');raw.review.artifactId=artifact.id;const bound=validateVerificationRequest(raw);expect(validateReviewArtifact(artifact,'run',bound)).toMatchObject({producer:'producer-session',assurance:'self_attested'});expect(()=>makeReviewArtifact('run',req,req.review.reviewer)).toThrow('distinct');expect(()=>validateReviewArtifact({...artifact,rationale:'changed'},'run',bound)).toThrow('does not bind');});
|
|
test('executor observations have a strict helper-owned shape',()=>{expect(()=>validateVerificationObservation({booted:true,legitimate:true,security:'pass',existingTests:true,output:'ok',inputHash:'',tested:true})).toThrow('Unexpected');expect(()=>validateVerificationObservation({booted:'yes',legitimate:true,security:'pass',existingTests:true,output:'ok',inputHash:''})).toThrow('booleans');});
|
|
test('secret-bearing fixtures cannot enter a replayable verification bundle',async()=>{const runDir=tmp(),snapshot=path.join(runDir,'snapshot');fs.mkdirSync(snapshot);fs.writeFileSync(path.join(snapshot,'app.js'),'vulnerable\n');const raw:any=request('vulnerable\n','fixed\n');raw.review.reviewedPatchHash=patchHash(raw);raw.fixtures={'secret.txt':CREDENTIAL_CANARY};const manifest:any={entries:[{path:'app.js',transformation:undefined}]};const runtime:any={id:'node',image:'runtime@sha256:'+'a'.repeat(64),platform:'linux/amd64'};expect(verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime,verifier:runtime,policyHash:'c'.repeat(64),archives:[],executor:{observe:async()=>{throw new Error('must not execute');}},persist:false})).rejects.toMatchObject({code:'REDACTION_FAILED'});});
|
|
test('declared patches require exact pristine preimages',()=>{const root=tmp(),before=path.join(root,'before'),after=path.join(root,'after');fs.mkdirSync(before);fs.writeFileSync(path.join(before,'app.js'),'changed\n');const raw:any=request('vulnerable\n','fixed\n');raw.review.reviewedPatchHash=patchHash(raw);expect(()=>preparePatchedSource(before,after,validateVerificationRequest(raw))).toThrow('preimage');});
|
|
test('helper derives dependency and configuration patch effects',()=>{expect(fileEffect('package.json')).toBe('dependency');expect(fileEffect('apps/x/pyproject.toml')).toBe('dependency');expect(fileEffect('config/environments/test.rb')).toBe('configuration');const root=tmp(),before=path.join(root,'before'),after=path.join(root,'after');fs.mkdirSync(before);fs.writeFileSync(path.join(before,'package.json'),'{}');const raw:any=request('vulnerable\n','fixed\n');raw.changes=[{path:'package.json',beforeSha256:sha256('{}'),after:'{"dependencies":{}}',effect:'configuration'}];raw.boundaryFiles=['package.json'];raw.review.reviewedPatchHash=patchHash(raw);expect(()=>preparePatchedSource(before,after,validateVerificationRequest(raw))).toThrow('must be declared as dependency');});
|
|
test('verification evidence stays outside both source trees and temporary copies are deleted on errors',async()=>{const runDir=tmp(),snapshot=path.join(runDir,'snapshot');fs.mkdirSync(snapshot);fs.writeFileSync(path.join(snapshot,'app.js'),'vulnerable\n',{mode:0o755});const testBody='test("ok",()=>{})\n';fs.writeFileSync(path.join(snapshot,'app.test.js'),testBody);const packageJson='{"scripts":{"test":"node --test"}}';fs.writeFileSync(path.join(snapshot,'package.json'),packageJson);const raw:any=request('vulnerable\n','fixed\n');raw.findingId='1abcdefabcdefabcdefabcdefabcdefa';raw.existingTests=[{executable:'/usr/local/bin/node',args:['--test','--test-reporter=tap','./app.test.js']}];raw.testFiles=['app.test.js'];raw.changes.push({path:'security/policy.js',beforeSha256:null,after:'export const enforced = true\n',effect:'source'});raw.review.reviewedPatchHash=patchHash(raw);const manifest:any={version:3,createdAt:'2026-01-01T00:00:00Z',expiresAt:'2026-01-08T00:00:00Z',root:'/repo',headCommit:'a'.repeat(40),originalHash:'b'.repeat(64),executionHash:treeHash(snapshot),entries:[{path:'app.js',originalHash:sha256('vulnerable\n'),executionHash:sha256('vulnerable\n'),bytes:11,mode:0o755},{path:'app.test.js',originalHash:sha256(testBody),executionHash:sha256(testBody),bytes:Buffer.byteLength(testBody),mode:0o600},{path:'package.json',originalHash:sha256(packageJson),executionHash:sha256(packageJson),bytes:packageJson.length,mode:0o600}]};const runtime:any={id:'node',stack:'node',image:'runtime@sha256:'+'a'.repeat(64),platform:'linux/amd64'};const executor:any={observe:async(source:string,phase:string,_request:any,_runtime:any,_verifier:any,work:string)=>{expect(work.startsWith(source+path.sep)).toBe(false);fs.mkdirSync(path.join(work,phase),{recursive:true});fs.writeFileSync(path.join(work,phase,'policy.json'),'evidence');return{booted:true,legitimate:true,security:phase==='before'?'intended_failure':'pass',existingTests:true,output:'ok',inputHash:''};}};let unattested:any;try{await verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime,verifier:runtime,policyHash:'c'.repeat(64),archives:[],executor,persist:false});}catch(error){unattested=error;}expect(unattested).toMatchObject({code:'PREREQUISITE',attempt:{artifactKind:'repair_candidate',findingId:raw.findingId,reproduction:'reproduced',repair:'proposed',bundleIssued:false,testCompletionAssurance:'self_reported'}});expect(unattested.message).toContain('out-of-process external assertion witness');expect(fs.existsSync(path.join(runDir,'bundles'))).toBe(false);expect(fs.readdirSync(path.join(runDir,'verification'))).toEqual([]);expect(fs.statSync(path.join(snapshot,'app.js')).mode&0o777).toBe(0o755);const failing:any={observe:async()=>{throw new Error('stop');}};expect(verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime,verifier:runtime,policyHash:'c'.repeat(64),archives:[],executor:failing,persist:false})).rejects.toThrow('stop');expect(fs.readdirSync(path.join(runDir,'verification'))).toEqual([]);const afterFailure:any={observe:async(_source:string,phase:string)=>{if(phase==='after')throw new CsoError('TOOL_FAILED','after setup failed');return{booted:true,legitimate:true,security:'intended_failure',existingTests:true,output:'reproduced safely',inputHash:''};}};let failed:any;try{await verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime,verifier:runtime,policyHash:'c'.repeat(64),archives:[],executor:afterFailure});}catch(error){failed=error;}expect(failed).toMatchObject({code:'TOOL_FAILED',attempt:{findingId:raw.findingId,reproduction:'reproduced',repair:'failed',bundleIssued:false}});const attempt=failed.attempt,artifact=JSON.parse(fs.readFileSync(path.join(runDir,'verification-attempts',`${attempt.id}.json`),'utf8'));expect(artifact).toMatchObject({id:attempt.id,findingId:raw.findingId,reproduction:'reproduced',repair:'failed',bundleIssued:false});expect(fs.existsSync(path.join(runDir,'bundles'))).toBe(false);expect(fs.readdirSync(path.join(runDir,'verification'))).toEqual([]);const assertionFailure:any={observe:async(_source:string,phase:string)=>({booted:true,legitimate:true,security:'intended_failure',existingTests:true,output:phase==='before'?'reproduced safely':'repair remained vulnerable',inputHash:''})};let notRepaired:any;try{await verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime,verifier:runtime,policyHash:'c'.repeat(64),archives:[],executor:assertionFailure});}catch(error){notRepaired=error;}expect(notRepaired).toMatchObject({code:'ASSERTION_FAILED',attempt:{reproduction:'reproduced',repair:'failed',bundleIssued:false,after:{security:'intended_failure'}}});expect(fs.existsSync(path.join(runDir,'bundles'))).toBe(false);expect(fs.readdirSync(path.join(runDir,'verification-attempts'))).toHaveLength(2);const brokenStartup:any={observe:async()=>({booted:false,legitimate:false,security:'pass',existingTests:false,output:'application never started',inputHash:''})};let blocked:any;try{await verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime,verifier:runtime,policyHash:'c'.repeat(64),archives:[],executor:brokenStartup});}catch(error){blocked=error;}expect(blocked).toMatchObject({attempt:{reproduction:'blocked',repair:'failed',bundleIssued:false}});expect(fs.readdirSync(path.join(runDir,'verification-attempts'))).toHaveLength(3);fs.writeFileSync(path.join(snapshot,'unmanifested.txt'),'changed after snapshot identity\n');let executed=false;const mustNotExecute:any={observe:async()=>{executed=true;return{booted:true,legitimate:true,security:'pass',existingTests:true,output:'',inputHash:''};}};await expect(verifyRepair({runId:'run',runDir,manifest,rawRequest:raw,runtime,verifier:runtime,policyHash:'c'.repeat(64),archives:[],executor:mustNotExecute,persist:false})).rejects.toMatchObject({code:'INCOMPATIBLE_INPUT'});expect(executed).toBe(false);});
|
|
test('handle-bearing bundles validate against matching source copied to a new root',()=>{
|
|
const root=tmp(),before=path.join(root,'original'),matching=path.join(root,'matching'),after=path.join(root,'after');fs.mkdirSync(before);
|
|
fs.writeFileSync(path.join(before,'app.js'),'vulnerable\n');fs.writeFileSync(path.join(before,'test.js'),'test("ok",()=>{})\n');
|
|
const appId=snapshotPathId(before,'app.js'),testId=snapshotPathId(before,'test.js'),appHandle=snapshotPathHandle(appId),testHandle=snapshotPathHandle(testId),raw:any=request('vulnerable\n','fixed\n');
|
|
raw.start.args=[appHandle];raw.existingTests[0].args=[`./${testHandle}`];raw.boundaryFiles=[appHandle];raw.testFiles=[testHandle];raw.changes[0].path=appHandle;raw.review.reviewedPatchHash=patchHash(raw);
|
|
const identityRequest=validateVerificationRequest(raw),entries=[{path:'app.js',pathId:appId},{path:'test.js',pathId:testId}],manifest:any={root:before,originalHash:'d'.repeat(64),executionHash:treeHash(before),entries},executionRequest=resolveVerificationRequestPaths(manifest,identityRequest);
|
|
preparePatchedSource(before,after,executionRequest);const runtime:any={id:'node',image:'runtime@sha256:'+'a'.repeat(64),platform:'linux/amd64'},params:any={runId:'run',manifest,request:executionRequest,identityRequest,runtime,verifier:runtime,before:{booted:true,legitimate:true,security:'intended_failure',existingTests:true,output:'before',inputHash:''},after:{booted:true,legitimate:true,security:'pass',existingTests:true,output:'after',inputHash:''},beforeRoot:before,afterRoot:after,policyHash:'c'.repeat(64),auditPolicyHash:'e'.repeat(64),archives:[],testToolchain:'runtime'},bundle=authenticatedBundleFixture(certify(params),params);
|
|
fs.cpSync(before,matching,{recursive:true});const matchingManifest:any={...manifest,root:matching,entries:entries.map(entry=>({...entry,pathId:snapshotPathId(matching,entry.path)}))};
|
|
expect(snapshotPathId(matching,'app.js')).toBe(appId);expect(treeHash(matching)).toBe(manifest.executionHash);expect(bundle.request.start.args).toEqual([appHandle]);expect(bundle.request.existingTests[0].args).toEqual([`./${testHandle}`]);expect(()=>validateRepairBundle(bundle,bundle.id,matching)).toThrow('matching snapshot manifest');expect(validateRepairBundle(bundle,bundle.id,matching,matchingManifest).id).toBe(bundle.id);
|
|
});
|
|
test('reserved authenticated bundle reader detects changed observations, replay inputs, and retention timestamps',()=>{const root=tmp(),before=path.join(root,'before'),after=path.join(root,'after');fs.mkdirSync(before);fs.writeFileSync(path.join(before,'app.js'),'vulnerable\n');fs.writeFileSync(path.join(before,'test.js'),'pass\n');const raw:any=request('vulnerable\n','fixed\n');raw.review.reviewedPatchHash=patchHash(raw);const req=validateVerificationRequest(raw);preparePatchedSource(before,after,req);const params:any={runId:'run',manifest:{originalHash:'d'.repeat(64),executionHash:treeHash(before),entries:[]},request:req,runtime:{id:'node',image:'runtime@sha256:'+'a'.repeat(64),platform:'linux/amd64'},verifier:{image:'runtime@sha256:'+'a'.repeat(64)},before:{booted:true,legitimate:true,security:'intended_failure',existingTests:true,output:'before',inputHash:''},after:{booted:true,legitimate:true,security:'pass',existingTests:true,output:'after',inputHash:''},beforeRoot:before,afterRoot:after,policyHash:'c'.repeat(64),auditPolicyHash:'e'.repeat(64),archives:[],testToolchain:'runtime'};const certified=certify(params),bundle=authenticatedBundleFixture(certified,params);expect(validateRepairBundle(bundle,bundle.id,before).id).toBe(bundle.id);expect(()=>validateRepairBundle({...bundle,verification:{...bundle.verification,after:{...bundle.verification.after,output:'tampered'}}},bundle.id,before)).toThrow('identity');const changed=structuredClone(bundle);changed.request.legitimate[0].path='/different';expect(()=>validateRepairBundle(changed,changed.id,before)).toThrow('harness');const expired=structuredClone(bundle);expired.expiresAt=new Date(Date.parse(expired.expiresAt)+1000).toISOString();expect(()=>validateRepairBundle(expired,expired.id,before)).toThrow('timestamps');const rebased=structuredClone(bundle);rebased.createdAt=new Date(Date.parse(rebased.createdAt)+1000).toISOString();rebased.expiresAt=new Date(Date.parse(rebased.createdAt)+30*86400_000).toISOString();expect(()=>validateRepairBundle(rebased,rebased.id,before)).toThrow('timestamps');});
|
|
test('project test-toolchain provenance requires equal prepared bytes and survives bundle identity rebinding',()=>{
|
|
const root=tmp(),before=path.join(root,'before'),after=path.join(root,'after');fs.mkdirSync(before);fs.writeFileSync(path.join(before,'app.js'),'vulnerable\n');fs.writeFileSync(path.join(before,'test.js'),'pass\n');const raw:any=request('vulnerable\n','fixed\n');raw.review.reviewedPatchHash=patchHash(raw);const req=validateVerificationRequest(raw);preparePatchedSource(before,after,req);const h=(value:string)=>value.repeat(64),proof=(dependency:string)=>({schemaVersion:1 as const,dependencyClosureHash:h('1'),configurationHash:h('2'),sourceProjectionHash:h('3'),preparedManifestHash:h('4'),preparedDependencyHash:dependency,receiptHash:h('5'),executionEnvironmentHash:h('6'),databaseHash:h('7'),transformations:[]});
|
|
const params:any={runId:'run',manifest:{originalHash:h('8'),executionHash:treeHash(before),entries:[]},request:req,runtime:{id:'node',image:`runtime@sha256:${h('a')}`,platform:'linux/amd64'},verifier:{image:`runtime@sha256:${h('a')}`},before:{booted:true,legitimate:true,security:'intended_failure',existingTests:true,output:'before',inputHash:''},after:{booted:true,legitimate:true,security:'pass',existingTests:true,output:'after',inputHash:''},beforeRoot:before,afterRoot:after,policyHash:h('c'),auditPolicyHash:h('e'),archives:[],testToolchain:'project',preparation:{before:proof(h('9')),after:proof(h('9'))}};
|
|
const certified=certify(params),bundle=authenticatedBundleFixture(certified,params);expect(certified.manifest.testToolchain).toBe('project');expect(certified.bundle).toBeUndefined();expect(validateRepairBundle(bundle,bundle.id,before).id).toBe(bundle.id);
|
|
const missing=structuredClone(bundle);delete missing.preparation;expect(()=>validateRepairBundle(missing,missing.id,before)).toThrow('omitted project test-toolchain');
|
|
const drift=structuredClone(bundle);drift.preparation!.after.preparedDependencyHash=h('b');drift.verification.preparationHash=sha256(canonical(drift.preparation));drift.verification.id='';const rebound=verificationIdentity(drift.verification);drift.verification.id=rebound;drift.id=rebound;expect(()=>validateRepairBundle(drift,rebound,before)).toThrow('test toolchain changed');
|
|
expect(()=>certify({...params,preparation:undefined})).toThrow('require before/after prepared dependency proofs');expect(()=>certify({...params,preparation:{before:proof(h('9')),after:proof(h('b'))}})).toThrow('toolchain bytes changed');
|
|
});
|
|
});
|
|
function tree(root:string){return sha256(JSON.stringify(fs.readdirSync(root).sort().map(p=>{const file=path.join(root,p),stat=fs.statSync(file);return[p,sha256(fs.readFileSync(file)),stat.mode&0o777];})));}
|