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,'financial-receipt-http.json');if(fs.existsSync(out)||!fs.existsSync(path.join(root,'financial-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,'financial-receipt-fixture.json')),base='/api/general-ledger/financial-receipts/',api=base+'recognition/'+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 denied');await p.enter('prepare');await v.enter('validate');let r=await p.request(api);ok(r.status===200&&r.data.domain==='recognition'&&JSON.stringify(r.data.result)===JSON.stringify(fixture.result),'Original recognition result');ok(r.headers.get('cache-control').includes('no-store'),'Private receipt');r=await p.request(base+'settlement/'+fixture.key);ok(r.status===200&&r.data.result.qa_fixture&&r.data.operation_executed===false,'Explicit domain same key no execution');ok((await v.request(api)).status===404,'Other actor receipt absent');ok((await v.request(base+'settlement/'+fixture.key)).status===403,'Separate settlement view right required');ok((await p.request('/api/general-ledger/receipts/'+fixture.key)).status===404,'No fallback to ledger');ok((await p.request(base+'unknown/'+fixture.key)).status===422,'Unknown domain refused');ok((await p.request(api+'?company_id=8')).status===422,'Scope injection refused');ok((await p.request(base+'recognition/invalid')).status===422,'Bad key refused');const page=await p.request('/general-ledger/costs?order_id='+g.order_id);ok(page.status===200&&page.text.includes('name="domain"')&&page.text.includes('value="settlement"'),'Integrated selector');fs.writeFileSync(path.join(root,'financial-receipt-page.html'),page.text);const old=await p.module('finance');ok((await p.request(api)).status===409,'Accounting context required');await p.module('accounting');ok((await p.request(api,undefined,undefined,{'X-SGF-Context':old})).status===409,'Stale generation refused');fs.writeFileSync(out,JSON.stringify({passed:true,checks,no_business_commands:true,actual_http:true,visual_review:false},null,2));console.log(JSON.stringify({passed:true,checks}));}finally{server.kill();fs.closeSync(log);}