/** Explicit operator process only. No HTTP, runtime import, role provisioning or READY. */ import assert from 'node:assert/strict' import path from 'node:path' import {pathToFileURL} from 'node:url' import {createPublicKey} from 'node:crypto' import {readProtected,protectedDirectory,sha} from './writer-profile/operator-files.mjs' import {approval,reconciliationApproval,poolOptions,roleKeys,assertJsDriverEnvironment} from './writer-profile/operator-contract.mjs' import {deploymentRequest} from './database-writer-bootstrap-operator.mjs' const hex=(v:unknown)=>typeof v==='string'&&/^[a-f0-9]{64}$/.test(v) const parse=(b:Buffer)=>JSON.parse(new TextDecoder('utf-8',{fatal:true}).decode(b)) const sourceCommands=['source-activate','source-revoke','source-status'] export async function main(args:string[]){ if(sourceCommands.includes(args[0]))return (await import('./writer-profile/source-activation.mjs')).sourceActivationMain(args) if(['maintenance-inspect','maintenance-resolve'].includes(args[0]))return (await import('./writer-profile/maintenance-resolution.mjs')).maintenanceMain(args) const activePreflight=args[0]==='source-preflight',preflight=activePreflight||args[0]==='preflight' const flags=['bootstrap','bootstrap-sha256','approval','approval-sha256','definition','definition-sha256','transport','transport-sha256','ca','source-registry','source-spki-sha256','journal'] if(activePreflight)flags.push('activation-directory','activation-sha256') assert((preflight||['publish','reconcile'].includes(args[0]))&&args.length===1+2*flags.length) assertJsDriverEnvironment(process.env) const values=new Map() for(let i=1;ivalues.get(name)! for(const flag of flags.filter(f=>f.endsWith('sha256')))assert(hex(get(flag))) const bootstrap=parse(await readProtected(get('bootstrap'),32768,get('bootstrap-sha256'))) assert(bootstrap.format==='application-writer-bootstrap-v1'&&bootstrap.publicationAuthorized===false&&bootstrap.readyAuthorized===false) const request=deploymentRequest(bootstrap.deploymentRequest),subject=bootstrap.verificationSubject assert(subject.installationId===request.installationId&&hex(subject.publicKeySpkiSha256)&&sha(createPublicKey(subject.publicKeyPem).export({format:'der',type:'spki'}))===subject.publicKeySpkiSha256) const pinned=(args[0]==='reconcile'?reconciliationApproval:approval)(parse(await readProtected(get('approval'),16384,get('approval-sha256')))) const definition=parse(await readProtected(get('definition'),4194304,get('definition-sha256'))) const transport=parse(await readProtected(get('transport'),16384,get('transport-sha256'))) const ca=await readProtected(get('ca'),65536,request.tls.caSha256) const options=poolOptions(transport,request,ca) await protectedDirectory(get('journal'));await protectedDirectory(get('source-registry')) const privateKeyFile=path.join(path.dirname(get('bootstrap')),'signing-private.pem') if(args[0]==='publish'){const key=await readProtected(privateKeyFile,8192);key.fill(0)} // All explicit trust files are checked before app helper/PG imports. No .env URL is used. // Existing source helper loads config/dotenv. Complete it BEFORE pg's first // import so a newly loaded NODE_PG_FORCE_NATIVE cannot select another driver. const {createProtectedDatabaseSourceBindingVerifier}=await import('./writer-profile/protected-source-registry.mjs') assertJsDriverEnvironment(process.env) const [{default:pg},{createConnectedPublisher,requireCurrentCatalogueDefinition},{collectSource44Catalogue,approvedDefinition}]=await Promise.all([ import('pg'),import('./writer-profile/publisher.mjs'),import('./writer-profile/catalogue.mjs')]) assertJsDriverEnvironment(process.env) const reviewedDefinition=approvedDefinition(definition) assert.equal(reviewedDefinition.definitionSha256,pinned.definitionSha256) if(args[0]!=='reconcile')requireCurrentCatalogueDefinition(pinned,reviewedDefinition) const installation=Object.freeze({...subject,roles:Object.fromEntries(roleKeys.map(k=>[k,request.roles[k].signedOid])),roleBindings:request.roles,expectedSource:request.source,tls:Object.freeze({...request.tls})}) const sourcePin={registryDirectory:get('source-registry'),installationId:subject.installationId,publicKeySpkiSha256:get('source-spki-sha256'),currentHeadSha256:request.sourceHeadSha256} // Use the same protected registry evidence for inspection and publication. const verifier=createProtectedDatabaseSourceBindingVerifier(sourcePin) async function connected(sourceVerifier:typeof verifier,deadlineAt:number){ const publisher=createConnectedPublisher(installation,(s:Parameters[0])=>collectSource44Catalogue(s,installation),sourceVerifier,pinned,reviewedDefinition) const pool=new pg.Pool(options) // A pool-level async error never becomes raw stdout or a retry signal. let asyncFailure=false;pool.on('error',()=>{asyncFailure=true}) let result,primary:unknown,failed=false try{result=preflight?await publisher.preflightCurrentProfile(pool,{deadlineAt}):args[0]==='reconcile'?await publisher.reconcilePendingPublication(pool,{journalDirectory:get('journal'),deadlineAt}):await publisher.publishCurrentProfile(pool,{privateKeyFile,expectedHeadSha256:pinned.expectedHeadSha256,journalDirectory:get('journal'),validityMs:pinned.validityMs,deadlineAt})} catch(error){primary=error;failed=true} try{await pool.end()}catch(error){primary??=error;failed=true} if(preflight&&result?.state==='matched'&&result.platformProtectionVerified===true&&!failed&&!asyncFailure)return {event:'application-writer-profile-preflight',outcome:'matched',epoch:result.epoch,headSha256:result.headSha256,notAfter:result.notAfter,sourceMatched:true,rolesMatched:true,catalogueMatched:true,platformProtectionVerified:true,writerAuthorized:false,cleanupUnconfirmed:false,automaticReplay:false,generationAuthenticated:false,readyAuthorized:false} if(result?.outcome==='committed')return {event:'application-writer-profile-publication',outcome:'committed',epoch:result.epoch,headSha256:result.headSha256,notAfter:result.notAfter, cleanupUnconfirmed:result.cleanupUnconfirmed||asyncFailure||failed,journalUnconfirmed:!!result.journalUnconfirmed,automaticReplay:false,generationAuthenticated:false,readyAuthorized:false} if(args[0]==='reconcile'&&result&&!failed&&!asyncFailure&&['idle','confirmed','not-committed'].includes(result.state))return {event:'application-writer-profile-reconciliation',outcome:result.state,headSha256:result.headSha256??null,cleanupUnconfirmed:false,journalUnconfirmed:false,automaticReplay:false,generationAuthenticated:false,readyAuthorized:false} throw primary??Error('Publisher terminal unconfirmed') } const deadlineAt=Date.now()+120000 if(!activePreflight)return connected(verifier,deadlineAt) const {withActiveSourcePreflight}=await import('./writer-profile/source-activation.mjs') const publisherRole=request.roles.publisher.name const expectedSource={...request.source,databaseOid:Number(request.source.databaseOid),sessionUser:publisherRole,currentUser:publisherRole} const result=await withActiveSourcePreflight({directory:get('activation-directory'),expectedSha256:get('activation-sha256'),sourcePin,expectedSource,tlsSpkiSha256:request.tls.spkiSha256,deadlineAt},verifier, guardedVerifier=>connected(guardedVerifier,deadlineAt)) assert.equal(result.event,'application-writer-profile-preflight') return {...result,event:'application-writer-profile-source-preflight',sourceActivationMatched:true} } if(process.argv[1]&&import.meta.url===pathToFileURL(path.resolve(process.argv[1])).href){ try{const result=await main(process.argv.slice(2));console.log(JSON.stringify(result));if(result.cleanupUnconfirmed||result.journalUnconfirmed)process.exitCode=2} catch(error){ const sourceCommand=sourceCommands.includes(process.argv[2]) const unknown=sourceCommand&&(error as NodeJS.ErrnoException|null)?.code==='SOURCE_ACTIVATION_TERMINAL_UNKNOWN' console.error(JSON.stringify({event:sourceCommand?(unknown?'database-source-activation-unknown':'database-source-activation-refused'): ['maintenance-inspect','maintenance-resolve'].includes(process.argv[2])?'database-maintenance-command-refused':process.argv[2]==='source-preflight'?'application-writer-profile-source-preflight-refused':'application-writer-profile-publication-refused',automaticReplay:false,inspectPendingBeforeRetry:true,readyAuthorized:false}));process.exitCode=unknown?2:1 } }