import fs from 'node:fs';import assert from 'node:assert/strict';import crypto from 'node:crypto';import {session} from './sgf-single-http.mjs'; const run=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')),root=run.root+'/private/receipt-composition-cc50a276c10c',file=root+'/analysis-http-20261110.json';let p=fs.existsSync(file)?JSON.parse(fs.readFileSync(file)):{operations:{},checks:[]};if(p.passed){console.log(JSON.stringify({passed:true,reused:true,proof:file}));process.exit();}const save=()=>fs.writeFileSync(file,JSON.stringify(p,null,2));const ok=(v,n)=>{assert(v,n);if(!p.checks.includes(n))p.checks.push(n);save();};const prep=await session('sgf:finance_prepare','finance'),review=await session('sgf:finance_review','finance');const get=async(s=prep,query='')=>{const r=await s.get('/api/financial-indicators'+query);assert.equal(r.status,200);return r.json();};const state=await get();ok(prep.identity.context.analysis_qa_enabled===true,'feature in authorized finance context');ok(state.source.available&&state.source.kind==='composed_qa_sources','actual composed cash/ledger source no harness');ok(state.source.cash_balance_minor==='95000'&&state.source.supplier_credit_minor==='10000'&&state.source.cash_expenses_minor==='5000'&&state.source.cash_receipts_minor==='100000','actual950/100 and50/1000 sources'); const def=metric=>{const {label,...d}=state.templates[metric];return{...d,scope_description:'Apenas as fontes QA seleccionadas, sem rácio geral ou efeito financeiro.',evidence:'Fonte Caixa conciliada e conta credora QA explicitamente conferidas na instalação.'};};const input=(action,metric,version,data)=>({action,...(metric?{metric}:{}),version,data,reason:'Conferência individual QA do critério, fontes e retrato exacto, sem efeito financeiro.'});const calc=id=>input('calculate',null,0,{criterion_id:id,as_of:'2026-11-10'}); const command=async(name,s,body)=>{if(p.operations[name]?.result)return p.operations[name].result;let op=p.operations[name];if(!op){op=p.operations[name]={key:crypto.randomUUID(),input:body};save();}if(!op.cut){const r=await s.command('/api/financial-indicators/preview',op.input,op.key);assert.equal(r.status,200,JSON.stringify(r.value));op.cut=r.value.preview;ok(r.value.impact.new_financial_effects===0&&!r.value.impact.real_company_criterion,'preview no real criterion or financial effect');save();}const r=await s.command('/api/financial-indicators/confirm',{preview:op.cut});assert.equal(r.status,200,JSON.stringify(r.value));op.result=r.value;save();const again=await s.command('/api/financial-indicators/confirm',{preview:op.cut});ok(again.status===200&&again.value.replayed&&again.value.id===r.value.id,'repeat '+name+' no duplication');return r.value;}; const coverage='cash_coverage_single_payable',expense='cash_expense_share';const a=await command('prepare-coverage',prep,input('prepare',coverage,0,def(coverage)));let denied=await prep.command('/api/financial-indicators/preview',calc(a.id));ok(denied.status===200&&denied.value.impact.result.state==='pending','unreviewed criterion never calculated as determined');const ar=await command('review-coverage',review,input('review',coverage,1,{decision:'reviewed'}));const ac=await command('calculate-coverage',prep,calc(ar.id));let r=await prep.get('/api/financial-indicators/records/'+ac.id+'?type=result');const coverageResult=await r.json();ok(r.status===200&&coverageResult.result.value==='9.50'&&coverageResult.result.exact_fraction==='19/2'&&coverageResult.result.unit==='times','actual source ratio950/100=9.5'); await command('prepare-expense',prep,input('prepare',expense,0,def(expense)));const er=await command('review-expense',review,input('review',expense,1,{decision:'reviewed'}));const ec=await command('calculate-expense',prep,calc(er.id));r=await prep.get('/api/financial-indicators/records/'+ec.id+'?type=result');const expenseResult=await r.json();ok(r.status===200&&expenseResult.result.value==='5.00'&&expenseResult.result.exact_fraction==='1/20'&&expenseResult.result.unit==='percent','actual expense share50/1000=5percent');ok(expenseResult.result.previous_period===null&&expenseResult.result.trend===null,'missing time series not zero trend');ok(expenseResult.source_snapshot.kind==='composed_qa_sources'&&!expenseResult.result.real_company_criterion,'actual source snapshot retained without normative claim'); r=await prep.get('/api/financial-indicators/results/'+ec.id+'/report');ok(r.status===200&&r.headers.get('content-type').includes('text/csv'),'internal report available');const bytes=Buffer.from(await r.arrayBuffer());ok(crypto.createHash('sha256').update(bytes).digest('hex')===r.headers.get('x-content-sha256'),'report checksum exact');ok(bytes.toString().includes('50.00')&&bytes.toString().includes('1000.00')&&bytes.toString().includes('NAO E RACIO GERAL'),'report source amounts and scope plain'); const read=await session('sgf:read_only','finance'),catalogue=await get(read,'?per_page=100&state=reviewed');ok(catalogue.records.total===2&&!catalogue.capabilities.prepare&&!catalogue.capabilities.review,'reviewed catalogue and read-only rights');const results=await get(read,'?view=results&per_page=100');ok(results.records.total===2,'only two saved results');const history=await get(read,'?view=history&metric='+coverage);ok(history.records.total===2&&history.metric_version===2,'criterion history version2');denied=await read.command('/api/financial-indicators/preview',input('prepare',coverage,2,def(coverage)));ok(denied.status===403,'read-only writer refused');const missing=await prep.command('/api/financial-indicators/preview',calc(null));ok(missing.status===200&&missing.value.impact.result.state==='pending','no criterion auto-selected');const foreign=await prep.command('/api/financial-indicators/preview',calc(2147483647));ok(foreign.status===403,'unscoped criterion refused');r=await prep.get('/api/financial-indicators?tenant_id=2');ok(r.status===422,'tenant override refused');const wrong=await session('sgf:finance_prepare','accounting');r=await wrong.get('/api/financial-indicators');ok([403,409].includes(r.status),'wrong module refused'); const fresh=await session('sgf:finance_prepare','finance');r=await fresh.get('/api/financial-indicators/receipts/'+p.operations['calculate-coverage'].key);const recovered=await r.json();ok(r.status===200&&recovered.result.id===ac.id&&recovered.operation_executed===false,'own result receipt recovered in fresh session');r=await review.get('/api/financial-indicators/receipts/'+p.operations['calculate-coverage'].key);ok(r.status===404,'other actor receipt denied');r=await read.get('/finance/indicators',{headers:{Accept:'text/html'}});ok(r.status===200&&(await r.text()).includes('não são rácios gerais'),'actual screen with explicit QA limits');p.passed=true;p.business_confirmations=6;p.criteria_events_retained=4;p.results_retained=2;p.origin_simulated=false;p.new_financial_effects=0;p.browser_visual_review=false;save();console.log(JSON.stringify({passed:true,checks:p.checks.length,proof:file}));