Files
SGF/scripts/stock-ledger-observer-run.mjs
2026-11-04 09:37:20 +02:00

13 lines
3.3 KiB
JavaScript

import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import {spawnSync} from 'node:child_process';
const nativeTag=process.argv[2];if(!/^[a-f0-9]{12}$/.test(nativeTag??''))throw Error('Explicit native QA book required');
const state=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')),n=JSON.parse(fs.readFileSync(path.join(state.root,'private/stock-ledger-'+nativeTag+'/settings.json')));if(state.port!==55439||n.cluster!=='sgf_modular_regression_'+state.id)throw Error('Unexpected native source');
const tag=crypto.randomBytes(6).toString('hex'),root=path.join(state.root,'private/stock-ledger-observer-'+tag),database='budget_core_sgf_'+tag,role='stock_ledger_sgf_'+tag,password=crypto.randomBytes(32).toString('hex'),reader='stock_valuation_read_'+nativeTag,readPassword=crypto.randomBytes(32).toString('hex');fs.mkdirSync(root);
const admin=fs.readFileSync(path.join(state.root,'private/admin-password.txt'),'utf8').trim(),pg=(input,db='postgres')=>{const r=spawnSync('C:/Program Files/PostgreSQL/17/bin/psql.exe',['-h','127.0.0.1','-p','55439','-U','sgf_regression_owner','-d',db,'-Atq','-v','ON_ERROR_STOP=1'],{input,encoding:'utf8',windowsHide:true,env:{...process.env,PGPASSWORD:admin}});if(r.status!==0)throw Error('Observer QA provisioning failed; preserve state');return r.stdout.trim();};if(pg("SELECT current_setting('cluster_name')")!==n.cluster)throw Error('Wrong physical cluster');
pg(`CREATE ROLE ${role} LOGIN PASSWORD '${password}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS; CREATE DATABASE ${database} OWNER ${role}; REVOKE ALL ON DATABASE ${database} FROM PUBLIC;
CREATE ROLE ${reader} LOGIN PASSWORD '${readPassword}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS; ALTER ROLE ${reader} SET default_transaction_read_only=on; GRANT CONNECT ON DATABASE ${n.database} TO ${reader};`);
pg(`GRANT USAGE ON SCHEMA public TO ${reader}; GRANT SELECT ON stock_movements,stock_items,warehouses,gl_stock_books,gl_stock_rates,gl_stock_rate_reviews,gl_journals,gl_lines,gl_accounts TO ${reader};`,n.database);
const storage=path.join(root,'storage');for(const d of ['framework/cache/data','framework/sessions','framework/views','logs','cache'])fs.mkdirSync(path.join(storage,d),{recursive:true});
const connection={driver:'pgsql',host:'127.0.0.1',port:55439,database:n.database,username:reader,password:readPassword,charset:'utf8',prefix:'',search_path:'public',sslmode:'prefer',url:null};
fs.writeFileSync(path.join(root,'settings.json'),JSON.stringify({tag,root,database,role,password,storage,run:state.id,cluster:n.cluster,app_key:'base64:'+crypto.randomBytes(32).toString('base64'),source:connection,native_root:n.root},null,2));
for(const phase of process.argv[3]==='prepare-only'?['setup']:['setup','proof']){const r=spawnSync('C:/laragon/tools/sgf-tempo/php-8.4.27/php.exe',[path.resolve('scripts/stock-ledger-observer-entry.php'),path.join(root,'settings.json'),phase],{encoding:'utf8',windowsHide:true,timeout:60000,maxBuffer:1024*1024});fs.writeFileSync(path.join(root,phase+'.log'),r.stdout+'\n'+r.stderr);console.log(JSON.stringify({tag,phase,exit_code:r.status,proof_present:fs.existsSync(path.join(root,phase+'.json'))}));if(r.status!==0||!fs.existsSync(path.join(root,phase+'.json'))){process.exitCode=1;break;}}