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

8 lines
3.7 KiB
JavaScript

import fs from 'node:fs';import path from 'node:path';import assert from 'node:assert/strict';import {spawnSync} from 'node:child_process';
const tag=process.argv[2];if(!/^[a-f0-9]{12}$/.test(tag??''))throw Error('Explicit demo required');const run=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')),root=path.join(run.root,'private/stock-ledger-'+tag),servers=JSON.parse(fs.readFileSync(path.join(root,'demo-servers.json'))),out=path.join(root,'demo-check.json');if(fs.existsSync(out))throw Error('Completed demo check preserved');let checks=0;const check=(v,n)=>{assert(v,n);checks++;};
const session=base=>{const jar=new Map();return async(url,headers={})=>{const r=await fetch(base+url,{redirect:'manual',headers:{...headers,...(jar.size?{Cookie:[...jar].map(([k,v])=>k+'='+v).join('; ')}:{})}});for(const c of r.headers.getSetCookie()){const first=c.split(';')[0],i=first.indexOf('=');jar.set(first.slice(0,i),first.slice(i+1));}return{status:r.status,body:await r.text(),location:r.headers.get('location')};};};
const native=session('http://127.0.0.1:'+servers.native.port);let r=await native('/qa/stock');check(r.status===200&&r.body.includes('2UN/100MZN'),'new native QA entry reachable');r=await native('/qa/stock-enter/prepare');const n=JSON.parse(r.body);r=await native('/stock-valuation');check(r.status===200&&r.body.includes('id="rate"')&&r.body.includes('Incompleto'),'frozen bundle workspace begins without rates');r=await native('/api/stock-valuation',{'X-Stock-Context':n.context,Accept:'application/json'});const nd=JSON.parse(r.body);check(r.status===200&&nd.stock.rates.length===0&&nd.ledger.journals.length===0&&nd.stock.physical_balance_milli===1500,'native demo decisions unconsumed');
const sgf=session('http://127.0.0.1:'+servers.sgf.port);r=await sgf('/qa/stock-observer/reader');const s=JSON.parse(r.body);r=await sgf('/api/stock-valuation-read',{'X-SGF-Context':s.context,Accept:'application/json'});const d=JSON.parse(r.body);check(r.status===200&&d.status==='pending'&&d.unposted_movements===3&&d.physical_quantity_milli===1500&&d.posted_stock_value_minor===0,'SGF observer shows actual quantity and pending valuation, not fictitious current value');check(d.current_source_dependencies_validated===false&&d.operation_executed===false,'SGF remains qualified read-only observer');r=await sgf('/general-ledger/stock-valuation');check(r.status===200&&r.body.includes('Conferência incompleta')&&!r.body.includes('<form'),'SGF initial page states pending conference without commands');r=await sgf('/');check(r.status===200&&r.body.includes('/build/assets/'),'private SGF build used by main navigation');const asset=r.body.match(/(?:src|href)="([^" ]*\/build\/assets\/[^" ]+\.js)"/)[1],assetPath=new URL(asset,'http://127.0.0.1:'+servers.sgf.port).pathname;r=await sgf(assetPath);check(r.status===200&&r.body.includes('stock_valuation_read'),'private navigation asset contains scoped stock observer integration');
const p=spawnSync('C:/laragon/tools/sgf-tempo/php-8.4.27/php.exe',[path.resolve('scripts/stock-ledger-entry.php'),path.join(root,'settings.json'),'demo-preservation'],{encoding:'utf8',windowsHide:true,timeout:30000});fs.writeFileSync(path.join(root,'demo-preservation.log'),p.stdout+p.stderr);check(p.status===0&&fs.existsSync(path.join(root,'demo-preservation.json')),'all initial native source rights rate and journal fingerprints preserved');
fs.writeFileSync(out,JSON.stringify({passed:true,checks,read_only_checks:true,initial_rates:0,initial_journals:0,initial_closures:0,native:servers.native.entry,sgf:servers.sgf.entry,private_build:true,pinned_bundle_manifest:servers.bundle_manifest_sha256,visual_review:false},null,2));console.log(JSON.stringify({passed:true,checks}));