const {app}=require('electron'); const fs=require('node:fs'),path=require('node:path'); function configureClient(connectionFile){ if(!connectionFile||!path.isAbsolute(connectionFile))throw Error('Absolute encrypted pairing file required'); app.setPath('userData',path.join(app.getPath('appData'),'safetynet-agent-helper')); } async function runClient(connectionFile,requestFile){ let stage='credential-store';try{ if(!requestFile)throw Error('Request file required'); stage='pairing';const descriptor=JSON.parse(fs.readFileSync(connectionFile,'utf8')); if(descriptor.format!=='windows-dpapi-v1')throw Error('Pairing format rejected'); const connection=JSON.parse(await require('./dpapi.cjs').capabilityCrypto('unprotect',descriptor.protectedConnection)); const origin=new URL(connection.address); if(origin.protocol!=='http:'||origin.hostname!=='127.0.0.1'||origin.username||origin.password||origin.pathname!=='/'||origin.search||origin.hash)throw Error('Agent endpoint rejected'); stage='request-file';const info=fs.statSync(requestFile);if(!info.isFile()||info.size>32768)throw Error('Request too large'); const body=fs.readFileSync(requestFile);if(body.length>32768)throw Error('Request too large');JSON.parse(body.toString()); stage='transport';const response=await require('./loopback-http.cjs').postLoopback({port:Number(origin.port),route:'/v1/actions',token:connection.token,body:JSON.parse(body.toString()),signal:AbortSignal.timeout(15000)}); stage='policy-response'; const result=response.body;if(response.status!==200)throw Error('Agent policy denied action'); process.stdout.write(JSON.stringify(result)+'\n');app.exit(0); }catch(error){error.clientStage=stage;throw error;} } module.exports={configureClient,runClient};