50 lines
6.3 KiB
JavaScript
50 lines
6.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 read=p=>JSON.parse(fs.readFileSync(p,'utf8').replace(/^\uFEFF/,''));
|
|
const hash=p=>crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex');
|
|
const state=read('C:/laragon/data/sgf-tempo/run/modular-regression-current.json');
|
|
const tag=process.argv[2],crossFile=path.resolve(process.argv[3]||''),functionalXml=path.resolve(process.argv[4]||'');
|
|
if(!/^[a-f0-9]{12}$/.test(tag||''))throw Error('Unexpected composition');
|
|
for(const p of [crossFile,functionalXml])if(path.dirname(p)!==path.resolve(state.root)||!/^stock-read-\d+\.(json|xml)$/.test(path.basename(p)))throw Error('Unexpected regression proof');
|
|
const root=path.join(state.root,'private','stock-composition-'+tag),native=read(path.join(root,'native-results.json')),cross=read(crossFile);
|
|
const nativeState=read(path.join(root,'state.json'));
|
|
if(nativeState.database!=='stock_read_compras_'+tag||nativeState.role!=='stock_read_qa_'+tag)throw Error('Unexpected native DB');
|
|
const artifact='../compras/packages/inventory-read/releases/0.1.0',manifest=read(artifact+'/manifest.json');
|
|
if(hash(artifact+'/manifest.json')!==native.package_manifest_sha256||native.package_manifest_sha256!==cross.native_package_manifest_sha256)throw Error('Artifact mismatch');
|
|
for(const [file,sha] of Object.entries(manifest.files))if(hash(artifact+'/'+file)!==sha||hash('packages/inventory-read/'+file)!==sha)throw Error('Two implementations differ');
|
|
if(hash('packages/inventory-read/src/InventoryReader.php')!==cross.reader_sha256||hash('packages/inventory-read/src/InventoryReadSession.php')!==cross.session_sha256)throw Error('Measured common source changed');
|
|
if(Object.keys(cross.cases).length!==12||!cross.cross_host_token_refused)throw Error('Incomplete comparison');
|
|
for(const [query,c] of Object.entries(cross.cases))if(!c.equivalent||c.sha256!==native.cases[query]?.sha256)throw Error('Comparison failed');
|
|
const junit=file=>{
|
|
const xml=fs.readFileSync(file,'utf8'),suite=xml.match(/<testsuite\b([^>]*)>/)?.[1];
|
|
const result=Object.fromEntries(['tests','assertions','errors','failures'].map(k=>[k,Number(suite?.match(new RegExp('\\b'+k+'="(\\d+)"'))?.[1])]));
|
|
if(!result.tests||result.errors!==0||result.failures!==0)throw Error('Invalid JUnit');return {...result,sha256:hash(file)};
|
|
};
|
|
const prior=read('docs/proofs/module-association-http-lock-summary-20261102.json');
|
|
for(const p of [prior.proof,...prior.previous_proofs])if(hash(p.path)!==p.sha256)throw Error('Earlier association proof changed');
|
|
const oldLoad=read('docs/proofs/stock-read-load-20261102.json');
|
|
if(oldLoad.source_sha256!==cross.reader_sha256)throw Error('Reader changed since valid load benchmark');
|
|
const env=fs.readFileSync(path.join(root,'app/.env.testing'),'utf8');
|
|
const password=env.match(/^DB_PASSWORD=([a-f0-9]+)$/m)?.[1];if(!password)throw Error('Private QA credentials unavailable');
|
|
const pg=spawnSync('C:/Program Files/PostgreSQL/17/bin/psql.exe',['-h','127.0.0.1','-p','55439','-U',nativeState.role,'-d',nativeState.database,'-At','-v','ON_ERROR_STOP=1'],{
|
|
encoding:'utf8',windowsHide:true,env:{...process.env,PGPASSWORD:password},input:"BEGIN READ ONLY; SELECT json_build_object('database',current_database(),'role',current_user,'cluster',current_setting('cluster_name'),'superuser',rolsuper,'create_database',rolcreatedb,'create_role',rolcreaterole,'replication',rolreplication,'bypass_rls',rolbypassrls) FROM pg_roles WHERE rolname=current_user; ROLLBACK;"});
|
|
if(pg.status!==0)throw Error('Native postcheck failed');
|
|
const nativePost=JSON.parse(pg.stdout.split(/\r?\n/).find(l=>l.startsWith('{')));
|
|
if(nativePost.database!==nativeState.database||nativePost.cluster!=='sgf_modular_regression_'+state.id||['superuser','create_database','create_role','replication','bypass_rls'].some(k=>nativePost[k]!==false))throw Error('Unexpected native role privileges');
|
|
const sgfPostRun=spawnSync('C:/laragon/tools/sgf-tempo/php-8.4.27/php.exe',['scripts/stock-read-state.php'],{encoding:'utf8',windowsHide:true});
|
|
if(sgfPostRun.status!==0)throw Error('SGF temporary rights not restored');
|
|
const summary={date:'2026-11-02',increment:'COMMON-STOCK-READ-COMPOSITION-SIM-v1',status:'two_application_read_api_compositions_verified',
|
|
package:{id:manifest.id,version:manifest.version,manifest_sha256:native.package_manifest_sha256,files:manifest.files,identical_verified_artifact:true,customer_dependency_on_sgf_source:false},
|
|
tests:{compras:junit(path.join(root,'native-junit.xml')),sgf_functional:junit(functionalXml),two_composition_parity:junit(crossFile.replace(/\.json$/,'.xml'))},
|
|
cases:cross.cases,cross_host_token_refused:true,native_checks:{roles_and_configured_profiles:native.native_roles_and_profiles_revalidated,warehouse_isolation:native.warehouse_isolation,stale_snapshot:native.stale_snapshot_refused,unknown_source:native.unknown_source_refused},
|
|
source_hashes:{sgf_adapter:hash('app/Modules/Inventory/StockReadController.php'),compras_adapter:hash('../compras/app/Http/Controllers/CommonStockReadController.php')},
|
|
preservation:{native_read_only_postcheck:nativePost,sgf_read_only_postcheck:JSON.parse(sgfPostRun.stdout),new_native_qa_database_retained:true,existing_databases_migrated:false,
|
|
prior_association_proofs_unchanged:true,existing_stock_load_reused_sha256:hash('docs/proofs/stock-read-load-20261102.json'),protected_six_records_untouched:true,blocked_cache_untouched:true,
|
|
public_rights_changed:false,purchasing_candidate_activated:false,demos_updated:false,publication:false,checkpoint:false},
|
|
limits:['Real application kernels/routes/middleware, preauthenticated synthetic users; no network login/MFA/TLS/browser proof.','Read-only API composition; existing native Stock page/writer unchanged.',
|
|
'Stock source is QA fixture, not migrated customer data; no receipt/consumption/business command executed.','No new load measurements; reader SQL unchanged and valid historical load retained.'],visual_review_pending:true,deployment_capacity_validated:false};
|
|
fs.writeFileSync('docs/proofs/stock-read-composition-20261102.json',JSON.stringify(summary,null,2)+'\n');
|
|
console.log(JSON.stringify({tests:summary.tests,equivalent_cases:12,identical_artifact:true,native_role_restricted:true,sgf_temporary_grants:summary.preservation.sgf_read_only_postcheck.temporary_stock_grants_remaining},null,2));
|