Files
stack/packages/bus/tests/model-key-loss-interaction.test.mjs
jason.woltje 362893d043 feat: integrate reviewed proxy page and managed model keys
Source-candidate: poe d9a564e6d20f5f0fd75ce45b12cbbf8bb4c9d568\nSource-candidate: magica38ba5762b06716db1dee00d0afec162656488f5c\nValidated321whole-file phase plus whole bus1349/model-proxy100/webui490; final gate tooling checks pending, not landed.
2026-10-26 12:04:21 -05:00

68 lines
7.8 KiB
JavaScript

// #652 diagnostic PREPARATION ONLY. Candidate6d3, not an observed regression.
// Real runtime/private records/fakeHTTP/owned OS children/original completed sweeps.
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import { join } from 'node:path';
import { reviewFixture } from './model-review-fixtures.mjs';
import { Credentials } from '../src/credentials.mjs';
import { ManagementClient } from '../../model-proxy/src/client.mjs';
import { startTimeOf } from '../../seat/src/proc.mjs';
const agent='demo/chief';
const absent=pid=>assert.throws(()=>fs.lstatSync(`/proc/${pid}`),error=>error.code==='ENOENT','own scratch process reaped; OS exit alone is not acquired runtime proof');
async function setup(t,{noRun=false,corrupt=null}={}){
const f=await reviewFixture(t,{overdue:true});
const privateView=new Credentials({storeRoot:join(f.configDir,'secrets','agents'),dataRoot:f.dataRoot,modelAgents:[agent]});let initial;
try{initial=privateView.modelRecord(agent);}finally{privateView.close();}
// Existing seed has unrelated retiring key1 and current key2. Associate own live
// run with CURRENT key2; retiring key1 forces the first real authoritative view.
f.entry.modelKeyId=initial.keyId;
if(noRun){await f.exit();absent(f.entry.pid);absent(f.entry.runnerPid);f.writeSessions([]);}
else f.writeSessions([{...f.entry,...(corrupt?{[corrupt]:corrupt==='modelKeyId'?'fedcba987654':'0'}:{})}]);
const bus=await f.boot();const proxy=await bus.modelPreflight({business:'demo',role:'chief'});
const first=await f.observeNextSweep(),manager=f.sweptManager;
assert.equal(typeof manager?.ensure,'function','real runtime controller observed through unchanged original sweep');
if(!corrupt){assert.equal(first.outcome,'fulfilled');assert.equal(bus.credentials.modelRecord(agent).retiring.length,0,'unrelated retiring generation completed, current identity actually checked');}
else assert.equal(first.outcome,'proxy-stop-failed','initial corrupt identity refuses before proof');
const client=new ManagementClient({baseUrl:proxy.baseUrl,key:'fx647-manage'});
const loseCurrent=async verb=>{
const old=bus.credentials.modelRecord(agent),before=await client.getKeys();assert.equal(before.includes(old.key),true,'setup current remotely present before deliberate loss');
await client.putKeys(before.filter(key=>key!==old.key));const confirmed=await client.getKeys();assert.equal(confirmed.includes(old.key),false,'real HTTP confirms remote absence');assert.equal(await client.probeKey(old.key),401);
const answer=await manager[verb](agent),after=bus.credentials.modelRecord(agent);
assert.equal(answer.key===old.key,false,'accepted absent-current contract issued fresh generation');assert.equal(after.retiring.some(r=>r.keyId===old.keyId),false,'absent old current not appended');assert.equal(f.state.keys.includes(old.key),false,'old current never restored');assert.equal(f.state.keys.includes(answer.key),true);return after;
};
const laterRetirement=async()=>{
const retiring=bus.credentials.modelRecord(agent);await manager.rotate(agent);const record=bus.credentials.modelRecord(agent);
assert.equal(record.retiring.some(r=>r.keyId===retiring.keyId),true,'later actual rotation appends confirmed current');
bus.credentials.writeModel(agent,{...record,retiring:record.retiring.map(r=>({...r,retireAt:new Date(Date.now()-60_000).toISOString()}))});
return {key:retiring.key,keyId:retiring.keyId};
};
const retained=later=>{assert.equal(f.state.keys.includes(later.key),true,'later generation remains remote');assert.equal(bus.credentials.modelRecord(agent).retiring.some(r=>r.keyId===later.keyId),true,'later retiring metadata retained');};
const retired=later=>{assert.equal(f.state.keys.includes(later.key),false,'later generation retires after exact own outer and runner OS exits');assert.equal(bus.credentials.modelRecord(agent).retiring.some(r=>r.keyId===later.keyId),false);};
// Establish terminal proof only through an associated retiring key and separately
// observed ORIGINAL sweeps, never infer it merely from ChildProcess close.
const acquireProof=async({outerOnly=false}={})=>{
const current=bus.credentials.modelRecord(agent);await manager.rotate(agent);
await f.exitOuter();absent(f.entry.pid);let seen=await f.observeNextSweep();assert.equal(seen.outcome,'fulfilled');assert.equal(f.state.keys.includes(current.key),true,'live runner retains associated key before grace');
assert.equal(startTimeOf(f.entry.runnerPid)===f.entry.runnerStartTime,true,'runner counterpart still exact/live');
if(outerOnly)return;
await f.exitRunner();absent(f.entry.runnerPid);seen=await f.observeNextSweep();assert.equal(seen.outcome,'fulfilled');assert.equal(f.state.keys.includes(current.key),false,'ordinary sweep removed associated key after both strict exits');
};
return {...f,bus,manager,initial,loseCurrent,laterRetirement,retained,retired,acquireProof};
}
for(const verb of ['ensure','rotate'])for(const registry of ['stale','empty'])test(`652 ${verb} absent current then ${registry} registry distinguishes OS exits from acquired proof`,async t=>{
const f=await setup(t);assert.equal(startTimeOf(f.entry.pid)===f.entry.startTime,true);assert.equal(startTimeOf(f.entry.runnerPid)===f.entry.runnerStartTime,true);
await f.loseCurrent(verb);const later=await f.laterRetirement();f.writeSessions(registry==='empty'?[]:[f.entry]);
let seen=await f.observeNextSweep();assert.equal(seen.outcome,'proxy-stop-failed');f.retained(later);
await f.exitOuter();absent(f.entry.pid);seen=await f.observeNextSweep();assert.equal(seen.outcome,'proxy-stop-failed');f.retained(later);assert.equal(startTimeOf(f.entry.runnerPid)===f.entry.runnerStartTime,true,'unbound live runner never signalled');
await f.exitRunner();absent(f.entry.runnerPid);seen=await f.observeNextSweep();
// Desired liveness assertion is a DIAGNOSTIC expectation only until measured and
// owner adjudicated. Predicted RED here is not claimed as an accepted blocker.
f.retired(later);assert.equal(seen.outcome,'fulfilled');
});
for(const verb of ['ensure','rotate'])test(`652 ${verb} absent current with valid no-run inventory retires normally`,async t=>{const f=await setup(t,{noRun:true});await f.loseCurrent(verb);const later=await f.laterRetirement();const seen=await f.observeNextSweep();assert.equal(seen.outcome,'fulfilled');f.retired(later);});
for(const verb of ['ensure','rotate'])test(`652 ${verb} previously acquired pair proof survives later absent-current repair`,async t=>{const f=await setup(t);await f.acquireProof();await f.loseCurrent(verb);const later=await f.laterRetirement();const seen=await f.observeNextSweep();assert.equal(seen.outcome,'fulfilled');f.retired(later);});
test('652 outer proof alone never authorizes stop of live unbound runner after key loss',async t=>{const f=await setup(t);await f.acquireProof({outerOnly:true});await f.loseCurrent('ensure');const later=await f.laterRetirement();const seen=await f.observeNextSweep();assert.equal(seen.outcome,'proxy-stop-failed');f.retained(later);assert.equal(startTimeOf(f.entry.runnerPid)===f.entry.runnerStartTime,true,'live counterpart retained and never signalled');});
for(const field of ['modelKeyId','startTime','runnerStartTime'])test(`652 initial corrupt ${field} stays refused after actual OS exits`,async t=>{const f=await setup(t,{corrupt:field});await f.loseCurrent('ensure');const later=await f.laterRetirement();await f.exit();absent(f.entry.pid);absent(f.entry.runnerPid);const seen=await f.observeNextSweep();assert.equal(seen.outcome,'proxy-stop-failed');f.retained(later);});
test('652 prior pair proof never permits a changed immutable persisted identity',async t=>{const f=await setup(t);await f.acquireProof();await f.loseCurrent('rotate');const later=await f.laterRetirement();f.writeSessions([{...f.entry,modelKeyId:'fedcba987654'}]);const seen=await f.observeNextSweep();assert.equal(seen.outcome,'proxy-stop-failed');f.retained(later);});