Source-candidate: poe d9a564e6d20f5f0fd75ce45b12cbbf8bb4c9d568\nSource-candidate: magica38ba5762b06716db1dee00d0afec162656488f5c\nValidated321whole-file phase plus whole bus1349/model-proxy100/webui490; final gate tooling checks pending, not landed.
101 lines
14 KiB
JavaScript
101 lines
14 KiB
JavaScript
// #656 STATIC preparation: real runtime inventory + Broker/writer/controller/HTTP.
|
|
// No code/test has run for this packet. Controlled faults are BEFORE verification.
|
|
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { startTimeOf } from '../../seat/src/proc.mjs';
|
|
import { revocationFixture, outcome, id } from './model-revocation-fixture.mjs';
|
|
const timeout=30000;
|
|
async function refused(f,how='fire'){const result=await outcome(()=>f.lifecycle(how));assert.equal(result.ok,false,'controlled lifecycle refuses');assert.equal(result.code,'credential-revoke-failed','existing lifecycle refusal code');assert.equal(f.state.callbackFailed,false,'owned transport mutation completed');return result;}
|
|
function retained(f){assert.equal(f.record()?.state==='revoking',true,'uncertain matched recovery retains cached revoking intent');assert.equal(f.exists(f.file),true,'existing final path retained');assert.equal(f.exists(f.temporary),true,'uncertain tmp path retained');}
|
|
|
|
for(const how of ['fire','delete'])test('656 matched durable revoking final and tmp '+how+' complete through real lifecycle',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true}),record=f.seed({retiring:2}),ids=[record.keyId,...record.retiring.map(r=>r.keyId)];
|
|
await assert.doesNotReject(()=>f.lifecycle(how),'matched intent '+how+' completes before membership publication');
|
|
assert.equal(f.counts.unlinkFinal,1,'composite '+how+' performs ONE final pathname unlink');assert.equal(f.record()===null,true);assert.equal(f.exists(f.file)||f.exists(f.temporary),false);assert.equal(f.listed(),false);assert.equal(ids.every(keyId=>f.state.probes.some(p=>p.keyId===keyId&&p.status===401)),true,'EVERY current and retiring key has confirmed401');assert.equal(f.openModelFds(),0);f.assertHistoryGuard();f.valueFree();
|
|
});
|
|
|
|
for(const how of ['fire','delete'])test('656 matched tmp unlink failure keeps durable cache and '+how+' retry completes',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();const before=f.membershipHash();f.faults.unlinkTmp=true;await refused(f,how);retained(f);assert.equal(f.membershipHash(),before);await assert.rejects(f.bus.modelPreflight({business:'demo',role:'aide'}),e=>e.code==='proxy-key-revoking');
|
|
f.faults.unlinkTmp=false;await assert.doesNotReject(()=>f.lifecycle(how),'recognized tmp unlink retry completes');assert.equal(f.record()===null,true);assert.equal(f.exists(f.file)||f.exists(f.temporary),false);assert.equal(f.listed(),false);f.valueFree();
|
|
});
|
|
|
|
test('656 failed remote confirmation preserves matching intent and membership without rollback claim',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true}),record=f.seed({retiring:2}),before=f.membershipHash();f.state.failPut=true;await refused(f);retained(f);assert.equal(f.membershipHash(),before);assert.equal([record.key,...record.retiring.map(r=>r.key)].every(key=>f.remoteHas(key)),true);f.valueFree();
|
|
});
|
|
test('656 non401 last retiring key never authorizes local deletion',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true}),record=f.seed({retiring:2}),old=record.retiring.at(-1),before=f.membershipHash();f.state.forceProbe.set(old.key,200);await refused(f);retained(f);assert.equal(f.membershipHash(),before);assert.equal(f.state.probes.some(p=>p.keyId===old.keyId&&p.status===401),false);assert.equal([record.keyId,...record.retiring.map(r=>r.keyId)].every(keyId=>f.state.probes.some(p=>p.keyId===keyId)),true);f.valueFree();
|
|
});
|
|
|
|
for(const mode of ['live-unbound','partial-exit','wrong-ticks','wrong-key','proc-read-error'])test('656 '+mode+' real inventory refuses matching recovery without signalling',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();const run=await f.ownRun({wrongTicks:mode==='wrong-ticks',wrongKey:mode==='wrong-key'});if(mode==='partial-exit')await run.exitOuter();if(mode==='proc-read-error')f.faults.procRead=run.entry.runnerPid;
|
|
const before=f.membershipHash(),puts=f.state.calls.filter(m=>m==='PUT').length;await refused(f);f.faults.procRead=null;retained(f);if(mode==='proc-read-error')assert.equal(f.counts.procRead>0,true,'owned proc read fault was reached');assert.equal(f.membershipHash(),before);assert.equal(f.state.calls.filter(m=>m==='PUT').length,puts,'known live or uncertain view causes no removal PUT');
|
|
if(mode==='partial-exit')assert.equal(startTimeOf(run.entry.runnerPid),run.entry.runnerStartTime,'live counterpart is retained');else assert.equal(run.alive(),true,'only owned stand-ins remain alive; discovery grants no stop authority');f.valueFree();
|
|
});
|
|
|
|
test('656 confirmed outer and runner exits permit matching intent recovery without rebind',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();const run=await f.ownRun();await run.exit();await assert.doesNotReject(()=>f.lifecycle('fire'),'confirmed exited pair permits matched intent completion');assert.equal(f.record()===null,true);assert.equal(f.exists(f.file)||f.exists(f.temporary),false);assert.equal(f.listed(),false);f.valueFree();
|
|
});
|
|
test('656 malformed actual persisted registry holds matching intent',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();f.writeSessions([]);fs.writeFileSync(join(f.dataRoot,'bus-host','sessions.json'),'not-json\n');const before=f.membershipHash();await refused(f);retained(f);assert.equal(f.membershipHash(),before);f.valueFree();
|
|
});
|
|
|
|
const negatives=[
|
|
['tmp symlink',f=>{fs.unlinkSync(f.temporary);const target=join(f.root,'unrelated');fs.writeFileSync(target,'owned unrelated\n',{mode:0o600});fs.symlinkSync(target,f.temporary);return {path:target,hash:id('owned unrelated\n')};}],
|
|
['tmp directory',f=>{fs.unlinkSync(f.temporary);fs.mkdirSync(f.temporary,{mode:0o700});}],
|
|
['tmp wrong mode',f=>fs.chmodSync(f.temporary,0o644)],
|
|
['tmp oversize',f=>fs.writeFileSync(f.temporary,'x'.repeat(16385),{mode:0o600})],
|
|
['tmp partial JSON',f=>fs.writeFileSync(f.temporary,'{',{mode:0o600})],
|
|
['tmp full metadata mismatch',f=>{const record=f.record();fs.writeFileSync(f.temporary,JSON.stringify({...record,rotateBy:'2098-01-01'})+'\n',{mode:0o600});}],
|
|
['tmp hardlink alias',f=>{fs.unlinkSync(f.temporary);fs.linkSync(f.file,f.temporary);}],
|
|
['final symlink',f=>{fs.unlinkSync(f.file);const target=join(f.root,'unrelated-final');fs.writeFileSync(target,'owned unrelated\n',{mode:0o600});fs.symlinkSync(target,f.file);return {path:target,hash:id('owned unrelated\n')};}],
|
|
['final wrong mode',f=>fs.chmodSync(f.file,0o644)],
|
|
['final malformed record',f=>fs.writeFileSync(f.file,'{',{mode:0o600})],
|
|
['unknown extra entry',f=>fs.writeFileSync(join(f.root,'config','secrets','agents','demo','aide','unknown'),'owned unrelated\n',{mode:0o600})],
|
|
];
|
|
for(const [name,mutate] of negatives)test('656 '+name+' is not recognized matching recovery authority',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();const unrelated=mutate(f);const before=f.membershipHash(),puts=f.state.calls.filter(m=>m==='PUT').length;await refused(f);retained(f);assert.equal(f.membershipHash(),before);assert.equal(f.state.calls.filter(m=>m==='PUT').length,puts);assert.equal(f.openModelFds(),0);if(unrelated)assert.equal(id(fs.readFileSync(unrelated.path)),unrelated.hash,'owned unrelated target is never followed or deleted');f.valueFree();
|
|
});
|
|
|
|
for(const target of ['tmp replacement','tmp content mutation','final replacement','final content mutation'])test('656 controlled '+target+' BEFORE final verification retains local intent',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed({retiring:1});let reached=false;
|
|
f.state.onProbe=()=>{reached=true;const path=target.startsWith('tmp')?f.temporary:f.file;if(target.includes('replacement')){const replacement=join(f.root,'owned-replacement');fs.writeFileSync(replacement,fs.readFileSync(path),{mode:0o600});fs.renameSync(replacement,path);}else{const value=f.record();fs.writeFileSync(path,JSON.stringify({...value,rotateBy:'2098-01-01'})+'\n',{mode:0o600});}};
|
|
const before=f.membershipHash();await refused(f);assert.equal(reached,true,'controlled fault actually ran before response401');retained(f);assert.equal(f.membershipHash(),before);assert.equal(f.openModelFds(),0);f.valueFree();
|
|
});
|
|
|
|
test('656 late actual registry publication after remote401 retains local intent without remote rollback',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true}),record=f.seed(),run=await f.ownRun({publish:false});let reached=false;f.state.onProbe=()=>{reached=true;f.writeSessions([run.entry]);};const before=f.membershipHash();await refused(f);assert.equal(reached,true);retained(f);assert.equal(f.membershipHash(),before);assert.equal(f.remoteHas(record.key),false,'late refusal does not pretend to roll back the remote operation');assert.equal(run.alive(),true);f.valueFree();
|
|
});
|
|
|
|
test('656 boot reconcile also removes strictly matched intent tmp only after every401',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true}),record=f.seed({retiring:2});await f.reboot();assert.equal(f.record()===null&&!f.exists(f.file)&&!f.exists(f.temporary),true,'boot reconcile completes recognized matching tmp recovery');assert.equal([record.keyId,...record.retiring.map(r=>r.keyId)].every(keyId=>f.state.probes.some(p=>p.keyId===keyId&&p.status===401)),true);f.valueFree();
|
|
});
|
|
test('656 active final rewrite self-repair remains a separate existing control',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed({valid:true});await f.lifecycle('fire');assert.equal(f.record()===null,true);assert.equal(f.exists(f.file)||f.exists(f.temporary),false);assert.equal(f.listed(),false);f.valueFree();
|
|
});
|
|
for(const how of ['fire','delete'])test('656 ordinary no-model no-tmp '+how+' stays ordinary idempotence',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});await f.lifecycle(how);assert.equal(f.record()===null,true);assert.equal(f.exists(f.file)||f.exists(f.temporary),false);assert.equal(f.listed(),false);f.valueFree();
|
|
});
|
|
test('656 unrelated service fence and bytes remain unchanged after model work',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();const other=join(f.storeRoot,'demo','aide','gitea'),body='owned unrelated\n';fs.writeFileSync(other,body,{mode:0o600});const before=f.membershipHash();await refused(f);assert.equal(f.membershipHash(),before);assert.equal(id(fs.readFileSync(other)),id(body));f.valueFree();
|
|
});
|
|
|
|
test('656 ordinary present no-tmp intent with missing boot registry refuses before removal',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true,missingBoot:true}),record=f.seed({matchingTmp:false}),before=f.membershipHash(),puts=f.state.calls.filter(m=>m==='PUT').length;
|
|
const failure=await outcome(()=>f.lifecycle('fire'));assert.equal(!failure.ok&&failure.code==='credential-revoke-failed',true,'ordinary present intent with missing boot view refuses before removal');assert.equal(f.record()?.state,'revoking');assert.equal(f.exists(f.file),true);assert.equal(f.state.calls.filter(m=>m==='PUT').length,puts);assert.equal(f.remoteHas(record.key),true);assert.equal(f.membershipHash(),before);
|
|
f.writeSessions([]);await refused(f);assert.equal(f.state.calls.filter(m=>m==='PUT').length,puts,'later Registry empty does not repair failed boot proof');assert.equal(f.membershipHash(),before);f.valueFree();
|
|
});
|
|
test('656 authoritative owned empty boot permits ordinary present no-tmp lifecycle completion',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed({matchingTmp:false});await f.lifecycle('fire');assert.equal(f.record()===null,true);assert.equal(f.exists(f.file)||f.exists(f.temporary),false);assert.equal(f.listed(),false);f.valueFree();
|
|
});
|
|
for(const late of ['final unlink failure','tmp absence read failure'])test('656 '+late+' after tmp removal stays revoking then authoritative restart completes',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();const before=f.membershipHash();if(late==='final unlink failure')f.faults.unlinkFinal=true;else f.faults.absenceTmp=true;
|
|
const failure=await outcome(()=>f.lifecycle('fire'));assert.equal(f.record()?.state==='revoking',true,'late recovery failure retains cached revoking fence');assert.equal(failure.ok,false);assert.equal(failure.code,'credential-revoke-failed');assert.equal(f.exists(f.file),true);assert.equal(f.exists(f.temporary),false,'tmp removal succeeded before this late refusal');assert.equal(f.membershipHash(),before);f.faults.unlinkFinal=false;f.faults.absenceTmp=false;
|
|
await f.reboot();assert.equal(f.record()===null,true);assert.equal(f.exists(f.file)||f.exists(f.temporary),false,'new authoritative boot reacquires strict proof, not vanished token');f.valueFree();
|
|
});
|
|
test('656 missing boot after tmp removed never turns remaining final into exit proof',{timeout},async t=>{
|
|
const f=await revocationFixture(t,{runtime:true});f.seed();f.faults.unlinkFinal=true;await outcome(()=>f.lifecycle('fire'));assert.equal(f.record()?.state==='revoking',true,'late recovery failure retains cached revoking fence');assert.equal(f.exists(f.temporary),false);f.faults.unlinkFinal=false;fs.unlinkSync(join(f.dataRoot,'bus-host','sessions.json'));const puts=f.state.calls.filter(m=>m==='PUT').length,before=f.membershipHash();await f.reboot();
|
|
assert.equal(f.record()?.state,'revoking');assert.equal(f.exists(f.file),true);assert.equal(f.state.calls.filter(m=>m==='PUT').length,puts,'failed boot refuses before new removal PUT');assert.equal(f.membershipHash(),before);await assert.rejects(f.bus.modelPreflight({business:'demo',role:'aide'}),e=>e.code==='proxy-key-revoking');f.writeSessions([]);await refused(f);assert.equal(f.state.calls.filter(m=>m==='PUT').length,puts);f.valueFree();
|
|
});
|