import fs from 'node:fs';import path from 'node:path';import net from 'node:net';import assert from 'node:assert/strict';import crypto from 'node:crypto';import {spawn} from 'node:child_process'; const read=p=>JSON.parse(fs.readFileSync(p,'utf8')),state=read('C:/laragon/data/sgf-tempo/run/modular-regression-current.json'),tag=process.argv[2];if(state.port!==55439||!/^[a-f0-9]{12}$/.test(tag??''))throw Error('Owned cost fixture required');const root=path.join(state.root,'private/ledger-'+tag),g=read(path.join(root,'cost-fixture.json')),out=path.join(root,'receipt-http-final.json');if(fs.existsSync(out)||!fs.existsSync(path.join(root,'receipt-fixture.json')))throw Error('Fresh HTTP proof with private baseline required'); await new Promise((resolve,reject)=>{const s=net.createServer();s.once('error',reject);s.listen(8047,'127.0.0.1',()=>s.close(resolve));});const log=fs.openSync(path.join(root,'cost-http-server.log'),'a'),server=spawn('C:/laragon/tools/sgf-tempo/php-8.4.27/php.exe',['-S','127.0.0.1:8047',path.resolve('scripts/ledger-cost-http-router.php')],{windowsHide:true,stdio:['ignore',log,log],env:{...process.env,LEDGER_QA_SETTINGS:path.join(root,'settings.json')}}); let checks=0;const ok=(v,m)=>{checks++;assert(v,m);};const client=()=>{const jar=new Map();let auth;const request=async(url,body,key=crypto.randomUUID(),extra={})=>{const r=await fetch('http://127.0.0.1:8047'+url,{method:body?'POST':'GET',headers:{Accept:'application/json',Cookie:[...jar].map(([k,v])=>k+'='+v).join('; '),'X-SGF-Context':auth?.context??'',...(body?{'Content-Type':'application/json','X-CSRF-TOKEN':auth?.csrf??'','Idempotency-Key':key}:{}),...extra},body:body?JSON.stringify(body):undefined,redirect:'manual',signal:AbortSignal.timeout(15000)});for(const c of r.headers.getSetCookie()){const p=c.split(';')[0],i=p.indexOf('=');jar.set(p.slice(0,i),p.slice(i+1));}const text=await r.text();let data;try{data=JSON.parse(text);}catch{}return{status:r.status,data,text,headers:r.headers};};return{request,enter:async role=>{const r=await request('/qa/cost-enter/'+role);ok(r.status===200,'Owned '+role+' entry');auth=r.data;ok(jar.has('sgf_cost_'+tag)&&!jar.has('XSRF-TOKEN'),'Separate session cookie and shared CSRF preserved');},module:async module=>{const old=auth.context,r=await request('/api/context',{...g.scope,module_id:module});ok(r.status===200,'Explicit module transition');auth={csrf:r.data.csrf,context:r.data.context.token};return old;}};}; const fixture=read(path.join(root,'receipt-fixture.json')),api='/api/general-ledger/receipts/'+fixture.key; try{const p=client(),v=client();let ready=false;for(let n=0;n<50&&!ready;n++){try{ready=(await p.request(api)).status===401;}catch{}if(!ready)await new Promise(r=>setTimeout(r,100));}ok(ready,'Anonymous receipt denied');await p.enter('prepare');await v.enter('validate');let r=await p.request(api);ok(r.status===200&&r.data.result.journal_id===fixture.journal_id&&r.data.operation_executed===false,'Own actual receipt recovered');ok(r.headers.get('cache-control').includes('no-store'),'Receipt never cached');ok((await v.request(api)).status===404,'Other actor same response as absent');ok((await p.request('/api/general-ledger/receipts/'+crypto.randomUUID())).status===404,'Absent key no inferred execution');ok((await p.request('/api/general-ledger/receipts/invalid')).status===422,'Malformed key denied');ok((await p.request(api+'?company_id=9')).status===422,'Injected scope denied');let page=await p.request('/general-ledger/costs?order_id='+g.order_id);ok(page.status===200&&page.text.includes('receipt-lookup')&&page.text.includes('Chave do pedido:'),'Recovery form and command key on errors integrated');fs.writeFileSync(path.join(root,'receipt-page.html'),page.text);const old=await p.module('finance');ok((await p.request(api)).status===409,'Wrong module denied');await p.module('accounting');ok((await p.request(api,undefined,undefined,{'X-SGF-Context':old})).status===409,'Stale context denied');fs.writeFileSync(out,JSON.stringify({passed:true,checks,actual_http:true,no_business_commands:true,visual_review:false},null,2));console.log(JSON.stringify({passed:true,checks}));}finally{server.kill();fs.closeSync(log);}