Source-candidate: poe d9a564e6d20f5f0fd75ce45b12cbbf8bb4c9d568\nSource-candidate: magica38ba5762b06716db1dee00d0afec162656488f5c\nValidated321whole-file phase plus whole bus1349/model-proxy100/webui490; final gate tooling checks pending, not landed.
68 lines
7.8 KiB
JavaScript
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);});
|