Files
multi-simadmin/packages/operation-registry/test/independent-safety-baseline.test.ts

60 lines
3.8 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { execFileSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { upstream58e2204Operations } from '../src/upstream-58e2204.ts';
const PHASE_0_2_COMMIT='9dffadbec271227da7ffb192f31dc78c6ee3c2be';
const BASELINE_PATH='packages/operation-registry/src/upstream-58e2204.ts';
const repoRoot=fileURLToPath(new URL('../../../',import.meta.url));
const safetyFields=['operationId','riskLevel','confirmationPolicy','capability','executionPolicy'] as const;
type SafetyRow=Record<(typeof safetyFields)[number],string>;
function git(...args:string[]){return execFileSync('git',args,{cwd:repoRoot,encoding:'utf8',stdio:['ignore','pipe','pipe']}).trim();}
/** Parse only the JSON array literal assigned to the frozen raw operations constant; never evaluate TypeScript. */
export function parseFrozenSafetyBaseline(source:string):SafetyRow[]{
const marker='const rawUpstream58e2204Operations = ';
const start=source.indexOf('[',source.indexOf(marker)+marker.length);
assert.ok(source.includes(marker)&&start>=0,'frozen operation array marker missing');
let quoted=false,escaped=false,depth=0,end=-1;
for(let i=start;i<source.length;i++){
const ch=source[i];
if(quoted){if(escaped)escaped=false;else if(ch==='\\')escaped=true;else if(ch==='"')quoted=false;continue;}
if(ch==='"'){quoted=true;continue;}if(ch==='[')depth++;else if(ch===']'&&--depth===0){end=i+1;break;}
}
assert.ok(end>start,'unterminated frozen operation array');
const parsed=JSON.parse(source.slice(start,end));
assert.ok(Array.isArray(parsed),'frozen operation baseline is not an array');
return parsed.map((row:any,index:number)=>Object.fromEntries(safetyFields.map(field=>{assert.equal(typeof row?.[field],'string',`baseline row ${index} missing ${field}`);return [field,row[field]];})) as SafetyRow);
}
export function assertExactSafetyBaseline(actual:readonly SafetyRow[],expected:readonly SafetyRow[]){
assert.equal(expected.length,117,'independent baseline must contain exactly 117 operations');
assert.equal(new Set(expected.map(x=>x.operationId)).size,117,'independent baseline operationIds must be unique');
assert.equal(actual.length,117,'current Registry must contain exactly 117 operations');
assert.equal(new Set(actual.map(x=>x.operationId)).size,117,'current Registry operationIds must be unique');
const sort=(rows:readonly SafetyRow[])=>[...rows].sort((a,b)=>a.operationId.localeCompare(b.operationId));
assert.deepEqual(sort(actual),sort(expected),'current Registry safety fields differ from frozen Phase 0.2 Git object; update requires explicit safety review');
}
const project=(rows:readonly any[]):SafetyRow[]=>rows.map(row=>Object.fromEntries(safetyFields.map(field=>[field,row[field]])) as SafetyRow);
test('independent Phase 0.2 Git object freezes all 117 Registry safety decisions',()=>{
assert.equal(git('rev-parse','9dffadb'),PHASE_0_2_COMMIT);
assert.equal(git('cat-file','-t',PHASE_0_2_COMMIT),'commit');
const baseline=parseFrozenSafetyBaseline(git('show',`${PHASE_0_2_COMMIT}:${BASELINE_PATH}`));
assertExactSafetyBaseline(project(upstream58e2204Operations),baseline);
});
test('independent safety comparison rejects risk, confirmation, capability and execution-policy mutations',()=>{
const baseline=parseFrozenSafetyBaseline(git('show',`${PHASE_0_2_COMMIT}:${BASELINE_PATH}`));
const mutations:[string,string,string][]=[
['postData','riskLevel','R0'],
['postSmsSend','confirmationPolicy','none'],
['postSmsSend','capability','query'],
['postSmsSend','executionPolicy','dedicatedFlow']
];
for(const [operationId,field,value] of mutations){const current=structuredClone(project(upstream58e2204Operations));(current.find(x=>x.operationId===operationId)! as any)[field]=value;assert.throws(()=>assertExactSafetyBaseline(current,baseline),/safety fields differ/,`${operationId}:${field}`);}
});