Files
SGF/scripts/summarize-obligation-composition.mjs
2026-11-04 09:37:20 +02:00

12 lines
5.9 KiB
JavaScript

import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import assert from 'node:assert/strict';
const [qaTag,demoTag]=process.argv.slice(2);assert([qaTag,demoTag].every(t=>/^[a-f0-9]{12}$/.test(t??'')));
const run=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')),qa=path.join(run.root,'private/receipt-composition-'+qaTag),demo=path.join(run.root,'private/receipt-composition-'+demoTag),read=p=>JSON.parse(fs.readFileSync(p,'utf8')),hash=p=>crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex'),tests={};
for(const [name,base,file,count]of [['integration',qa,'obligation-result.json',35],['replay_source',qa,'obligation-replay.json',3],['boundaries',qa,'obligation-boundaries.json',6],['guards',qa,'obligation-guards.json',6],['navigation','.','docs/proofs/obligation-home-20261103.json',6],['demonstration',demo,'obligation-demo-smoke.json',13],['assets',demo,'obligation-demo-assets.json',3]]){const p=path.join(base,file),r=read(p);assert(r.passed);assert.equal(Array.isArray(r.checks)?r.checks.length:r.checks,count);tests[name]={file:base==='.'?file:'private/'+path.basename(base)+'/'+file,sha256:hash(p),checks:count,result:r};}
const count=Object.values(tests).reduce((n,t)=>n+t.checks,0);assert.equal(count,72);
const files=['app/Modules/Purchasing/ObligationController.php','app/Modules/Purchasing/InvoiceController.php','app/Modules/Purchasing/ReceiptRuntime.php','app/Modules/Identity/Services/IdentityWorkflow.php','app/Shared/Context/ModuleNavigation.php','config/common-payables.php','config/receipt_qa.php','routes/web.php','resources/js/PurchasingHome.jsx','resources/views/supplier-invoice-workspace.blade.php','resources/views/supplier-obligation-workspace.blade.php','public/supplier-obligation-workspace.mjs'];
for(const base of [qa,demo])for(const file of files)assert.equal(hash(path.join(base,'app',file)),hash(file),'tested composition '+file);
const sources=files.map(file=>({file,sha256:hash(file)}));const pins=[];for(const base of [qa,demo]){const result={};for(const dir of ['bundle','economic','internal']){const p=path.join(base,dir,'manifest.json');result[dir]=hash(p);for(const [f,h]of Object.entries(read(p).files))assert.equal(hash(path.join(base,dir,f)),h);}pins.push(result);}assert.deepEqual(pins[0],pins[1]);assert.deepEqual(pins[0],read('docs/proofs/supplier-invoice-composition-20261103.json').pinned_native_manifests);
const previous=['docs/proofs/supplier-invoice-composition-20261103.json','docs/proofs/geography-composition-20261103.json','docs/proofs/module-association-consolidation-summary-20261102.json'].map(file=>({file,sha256:hash(file)})),assoc=read(previous.at(-1).file);assert.equal(hash('app/Modules/Identity/Services/ModuleAssociationReview.php'),assoc.source_sha256);assert.equal(hash('app/Modules/Identity/Http/ModuleRecordsController.php'),assoc.controller_sha256);assert.equal(hash('packages/purchasing/current.json'),read(previous[0].file).preservation.installed_purchasing_sha256);
const writer=['Payables.php','PayablesSchema.php','ReceiptReader.php','HistoricalPayments.php','SupplierSettlements.php'].map(file=>({file:'packages/payables/src/'+file,sha256:hash('packages/payables/src/'+file)}));for(const base of [qa,demo])for(const pin of writer)assert.equal(hash(path.join(base,'app',pin.file)),pin.sha256);
const out='docs/proofs/supplier-obligation-composition-20261103.json';assert(!fs.existsSync(out));fs.writeFileSync(out,JSON.stringify({date:new Date().toISOString(),increment:'SGF-INVOICE-TO-PAYABLE-QA-v1',passed:true,functional_code:true,checks:count,tests,sources,shared_writer_sources:writer,pinned_native_manifests:pins[0],canonical_authority:{native_book:true,imported_host_mirror:false,source_instance:'same qa-stock-ledger identity as original native provisioning',principal_minor:10000,obligations:1,recognition_events:1,due_on:null,payments_created:0,additional_stock_or_budget_effect:false,ledger_posted:false},demo:{port:8071,approved_award_prepared:true,main_orders:0,receipts:0,invoices:0,proposals:0,obligations:0,preparer_url:'http://127.0.0.1:8071/qa/enter/issuer?open=1&obligations=1',reviewer_url:'http://127.0.0.1:8071/qa/enter/reviewer?open=1&obligations=1'},qa_rights:['purchasing_obligations.view','purchasing_obligations.prepare','purchasing_obligations.validate'],prior_proofs_preserved:previous,preservation:{installed_purchasing_sha256:hash('packages/purchasing/current.json'),target_database_connected:false,protected_six_records_changed:false,blocked_cache_cleared:false,previous_demo_data_written:false,public_rights_changed:false,publication:false,checkpoint:false},limitations:['The35 integration checks preceded the added module-ownership rule; the6 later boundary checks verify the changed routing and preserve all financial evidence, without repeating the valid suite.','Changed-source replay is tested with the same native adapter/kernel using an injected duplicate validation audit inside a rollback-only transaction. It is an adversarial fixture, not another business validation.','Current native schema provisioning uses the current native project; runtime uses the previously tested frozen bundle. No general deployment compatibility is inferred.','Due date and overdue remain unknown. Recognition does not activate payment, history import, reconciliation, ledger or fiscal issuance.','Index uses server filters/pages25; evidence uses independent pages25 and current-state comparison reads only the latest capture. No sustained-load capacity conclusion.','The demonstration starts from an approved native award. Earlier request/sourcing/geography demonstrations remain separate fixtures, not falsely presented as one upgraded installation.','Visual review and production configuration, least-privilege installation and deployment capacity remain pending.'],visual_review_pending:true,deployment_capacity_validated:false},null,2)+'\n');console.log(JSON.stringify({output:out,checks:count,demo_port:8071}));