Files
safetynet/apps/network-broker/service-commit-gate.cjs
T

22 lines
1.4 KiB
JavaScript
Raw Normal View History

'use strict';
const {verifyServiceAcceptance}=require('./service-acceptance.cjs');
// Privileged, one-bootstrap gate. commitState must invoke the fixed protected
// native compare-and-swap store and acknowledge only after RegFlushKey succeeds.
// An in-memory callback in a test is not proof of Windows persistence.
function createServiceCommitGate({current,commitState}={}){
if(typeof current!=='function'||typeof commitState!=='function')throw Error('broker-bootstrap-invalid');
let used=false,failed=false;
const active=()=>{try{return !failed&&current()===true;}catch{return false;}};
return Object.freeze({async prepare(input){
if(used||!active())throw Error('broker-bootstrap-invalid');used=true;
try{
const plan=await verifyServiceAcceptance(input);if(!active())throw Error();
const request=Object.freeze({expectedPreviousSHA:plan.previousStateDigest,candidateState:plan.nextState});
if(Buffer.byteLength(JSON.stringify(request))>2097152)throw Error();
const receipt=await commitState(request);
if(!receipt||typeof receipt!=='object'||Array.isArray(receipt)||Object.keys(receipt).sort().join(',')!=='persisted,stateSha256'||receipt.persisted!==true||receipt.stateSha256!==plan.nextStateDigest||!active()||Date.now()>=plan.deployment.manifest.expiresAt)throw Error();
return plan;
}catch{failed=true;throw Error('broker-bootstrap-invalid');}
}});
}
module.exports={createServiceCommitGate};