'use strict'; /** Inherited private parent IPC only. The reviewed launcher supplies a fixed * factory in code; IPC cannot select modules, executable paths or commands. * This supplies lifecycle isolation, not a packaged/WFP-constrained broker. */ function runBrokerProcess(factory,{maxMessageBytes=65536}={}) { if(typeof factory!=='function'||typeof process.send!=='function'||!process.connected||!Number.isSafeInteger(maxMessageBytes)||maxMessageBytes<1||maxMessageBytes>65536)throw Error('broker-process-invalid'); let state='waiting',broker,closing; const send=value=>{if(process.connected)process.send(value,()=>{});}; const close=()=>{ if(closing)return closing; state='closing'; closing=Promise.resolve().then(()=>broker?.close()).catch(()=>{}).finally(()=>{if(process.connected)process.disconnect();}); return closing; }; process.once('disconnect',()=>{void close();}); process.on('message',message=>{ let serialized; try {serialized=JSON.stringify(message);} catch {serialized='';} if(!serialized||Buffer.byteLength(serialized)>maxMessageBytes||!message||typeof message!=='object'||Array.isArray(message)){send({type:'error',code:'invalid-message'});void close();return;} if(message.type==='stop'&&Object.keys(message).length===1){void close();return;} if(state!=='waiting'||message.type!=='start'||Object.keys(message).sort().join(',')!=='config,type'||!message.config||typeof message.config!=='object'||Array.isArray(message.config)){send({type:'error',code:'invalid-message'});void close();return;} state='starting'; Promise.resolve().then(()=>factory(message.config)).then(async created=>{ if(!created||typeof created.listen!=='function'||typeof created.close!=='function'||typeof created.capability!=='string'||!/^[a-zA-Z0-9_-]{43}$/.test(created.capability)||!['basic','bearer'].includes(created.authMode))throw Error('invalid-factory'); if(created.authMode==='basic'&&(!created.credentials||!/^safetynet-[a-f0-9]{32}$/.test(created.credentials.username)||created.credentials.password!==created.capability))throw Error('invalid-factory'); broker=created; if(state==='closing'){await broker.close();return;} const port=await broker.listen(); if(state==='closing'){await broker.close();return;} if(!Number.isSafeInteger(port)||port<1||port>65535)throw Error('invalid-listener'); state='ready';send({type:'ready',port,authMode:broker.authMode,capability:broker.capability,...(broker.authMode==='basic'?{credentials:{username:broker.credentials.username,password:broker.credentials.password}}:{})}); }).catch(()=>{send({type:'error',code:'startup-failed'});void close();}); }); return Object.freeze({close}); } module.exports={runBrokerProcess};