23 lines
1.4 KiB
JavaScript
23 lines
1.4 KiB
JavaScript
'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&¤t()===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};
|