Files
safetynet/apps/network-broker/wfp-revalidation.cjs
T

33 lines
1.9 KiB
JavaScript

'use strict';
const {validateTopology}=require('./wfp-topology.cjs');
// Adapter must come from a protected native service authority, never IPC JSON.
// Periodic reads supplement unreliable BFE notifications. Neither closes the
// privileged-change packet window; no atomic kernel claim is made here.
function createWfpRevalidation({readTopology,quarantine,intervalMs=500,deadlineMs=2000}={}){
if(typeof readTopology!=='function'||typeof quarantine!=='function'||!Number.isInteger(intervalMs)||intervalMs<100||intervalMs>1000||!Number.isInteger(deadlineMs)||deadlineMs<10||deadlineMs>5000)throw TypeError('Invalid WFP monitor');
let state='new',pending=false,timer,timeout;
function fail(reason){if(state==='closed'||state==='quarantined')return;state='quarantined';clearInterval(timer);clearTimeout(timeout);quarantine(reason);}
async function check(){
if(pending||state==='closed'||state==='quarantined')return false;
pending=true;
timeout=setTimeout(()=>fail('wfp-revalidation-timeout'),deadlineMs);timeout.unref?.();
try{
const snapshot=await readTopology();
if(state==='closed'||state==='quarantined')return false;
if(snapshot?.bfeRunning!==true){fail('wfp-bfe-unavailable');return false;}
const result=validateTopology(snapshot);
if(!result.safe){fail(result.reason);return false;}
return true;
}catch{fail('wfp-revalidation-unavailable');return false;}
finally{pending=false;clearTimeout(timeout);}
}
return Object.freeze({
async start(){if(state!=='new')throw Error('WFP monitor already started');state='starting';if(!await check())return false;if(state!=='starting')return false;state='verified';timer=setInterval(()=>{void check();},intervalMs);timer.unref?.();return true;},
changed(){fail('wfp-topology-changed');},
current(){return state==='verified';},
close(){state='closed';clearInterval(timer);clearTimeout(timeout);},
status(){return Object.freeze({state,pending});}
});
}
module.exports={createWfpRevalidation};