getStatusCode()===$status);}$ok($caught,'Expected combined access/completeness refusal');}; $case=function($name,$fn)use(&$checks,&$cases,$enter){$at=$checks;DB::beginTransaction();try{$fn();$cases[]=['name'=>$name,'checks'=>$checks-$at,'passed'=>true];}finally{while(DB::transactionLevel())DB::rollBack();$enter('read');}}; $fingerprint=function(){ $h=hash_init('sha256');foreach(['gl_journals','gl_lines','gl_commands','gl_period_checks','gl_period_closures','permission_grants','wo_orders','gl_cost_sources','dc_calculations','dc_outbox','si_invoices','sr_records','sr_effects','pa_obligations'] as $t){hash_update($h,$t);hash_update($h,DB::table($t)->orderBy($t==='dc_outbox'?'event_id':'id')->get()->toJson());}return hash_final($h);};$before=$fingerprint();$workspace=app(LedgerComposition::class); $case('bounded-recorded-source-panels',function()use($workspace,$enter,$ok,$cf){$d=$workspace->workspace($enter('read'));$ok($d['all_current_source_views']&&array_column($d['panels']['sales']['rows'],'invoice_id')===[$cf['invoice_id']],'Actual invoice visible in composed scope');$ok($d['panels']['costs']['rows'][0]['calculation_version']===2&&$d['panels']['costs']['rows'][0]['recorded_decision']==='approved','Recorded successor cost metadata');$ok($d['panels']['suppliers']['rows'][0]['principal_minor']===6000&&$d['book']['accounts']===[],'Principal labelled separately and account universe not loaded');$ok($d['recorded_state_is_not_current_conference']===true,'Navigation does not claim current dependency conference');$html=view('accounting.ledger-composition',['data'=>$workspace->workspace($enter('prepare'))])->render();foreach(['/general-ledger/sales?invoice_id=','/general-ledger/costs?order_id=','/general-ledger/flow?source=','data-action="period-prepare"'] as $text)$ok(str_contains($html,$text),'Workspace source/period entry: '.$text);}); $case('each-live-source-right-and-whole-book-right',function()use($workspace,$enter,$ok,$refuse,$scope,$g,$command){foreach(['service_invoices.view'=>'sales','service_receivables.view'=>'sales','workshop.view'=>'costs','direct_costs.view'=>'costs','supplier_payables.view'=>'suppliers'] as $right=>$panel){DB::beginTransaction();try{DB::table('permission_grants')->where($scope)->where('user_id',$g['actors']['prepare'])->where('permission',$right)->delete();$d=$workspace->workspace($enter('prepare'));$ok($d['panels'][$panel]===['allowed'=>false]&&!$d['all_current_source_views'],'Hidden source has no metadata/count: '.$right);$html=view('accounting.ledger-composition',['data'=>$d])->render();$ok(!str_contains($html,'data-action='),'Partial source access does not expose close forms');$refuse(fn()=>$command('prepare','period-prepare',['period_key'=>'QA-2026-10','reason'=>'No partial conference after provider right revoked.'])); }finally{DB::rollBack();}}DB::table('permission_grants')->where($scope)->where('user_id',$g['actors']['prepare'])->where('permission','general_ledger.view')->delete();$refuse(fn()=>$workspace->workspace($enter('prepare')));$refuse(fn()=>$workspace->workspace($enter('technician')));}); $case('eligible-foreign-contexts',function()use($workspace,$enter,$scope,$ok){foreach(['unit','company','tenant'] as $kind){DB::beginTransaction();try{$u=$enter('read');$company=$kind==='unit'?DB::table('companies')->where('id',$scope['company_id'])->first():($kind==='company'?DB::table('companies')->where('tenant_id',$scope['tenant_id'])->where('id','<>',$scope['company_id'])->first():DB::table('companies')->where('tenant_id','<>',$scope['tenant_id'])->first());$unit=DB::table('units')->insertGetId(['tenant_id'=>$company->tenant_id,'company_id'=>$company->id,'name'=>'SQL-ONLY foreign workspace '.$kind,'created_at'=>now(),'updated_at'=>now()]);if(!DB::table('company_memberships')->where(['tenant_id'=>$company->tenant_id,'company_id'=>$company->id,'user_id'=>$u->id])->exists())DB::table('company_memberships')->insert(['tenant_id'=>$company->tenant_id,'company_id'=>$company->id,'user_id'=>$u->id]);foreach(['company.view'=>null,'unit.view'=>$unit,'general_ledger.view'=>$unit,'service_invoices.view'=>$unit,'service_receivables.view'=>$unit,'workshop.view'=>$unit,'direct_costs.view'=>$unit,'supplier_payables.view'=>$unit] as $right=>$v)Tests\Support\IdentityFixture::grant($u->id,$company->tenant_id,$company->id,$right,$v);DB::table('pa_access')->insert(['tenant_id'=>$company->tenant_id,'company_id'=>$company->id,'unit_id'=>$unit,'user_id'=>$u->id,'person'=>'foreign-workspace-'.$u->id,'action'=>'view']);app(CompanyContext::class)->selectFor($u->id,$company->tenant_id,$company->id,$unit);try{$d=$workspace->workspace($u);}catch(DomainException){$ok(true,'Foreign context refused before any result');continue;}$ok(array_sum(array_map(fn($p)=>count($p['rows']??[]),$d['panels']))===0&&$d['book']['journals']===[],'No source/book leak in eligible foreign '.$kind);}finally{DB::rollBack();}}}); $case('independent-pagination-no-per-row-source-queries',function()use($workspace,$enter,$ok,$g){$template=(array)DB::table('wo_orders')->where('id',$g['order_id'])->first();$mapping=(array)DB::table('gl_cost_sources')->where('order_id',$g['order_id'])->first();unset($template['id'],$mapping['id']);for($i=0;$i<25;$i++){$row=$template;$row['reference']='SQL-ONLY-PAGE-'.$i;$id=DB::table('wo_orders')->insertGetId($row);DB::table('gl_cost_sources')->insert(array_merge($mapping,['order_id'=>$id]));}$db=DB::connection();$db->enableQueryLog();$db->flushQueryLog();$a=$workspace->workspace($enter('read'));$queriesA=count($db->getQueryLog());$db->flushQueryLog();$b=$workspace->workspace($enter('read'),['costs_page'=>2]);$queriesB=count($db->getQueryLog());$db->disableQueryLog();$ok(count($a['panels']['costs']['rows'])===25&&count($b['panels']['costs']['rows'])===1&&$b['panels']['costs']['pagination']['total']===26,'Cost pagination bounded25 with stable total26');$ok($a['panels']['sales']===$b['panels']['sales']&&$a['panels']['suppliers']===$b['panels']['suppliers'],'Changing costs page preserves other source pages');$ok($queriesA===$queriesB,'One row and25 rows use equal query count');$ok($b['panels']['costs']['rows'][0]['calculation_id']===null&&$b['panels']['costs']['rows'][0]['recorded_decision']===null,'SQL-only uncalculated perimeter is not labelled zero/approved');}); $case('unavailable-provider-not-zero',function()use($workspace,$enter,$refuse){DB::statement('ALTER TABLE pa_imported_sources RENAME TO qa_unavailable_receipts');$refuse(fn()=>$workspace->workspace($enter('read')),503);}); $case('feature-default-off-and-complete-period-blocker',function()use($workspace,$enter,$refuse,$command){config(['general_ledger.composition_enabled'=>false]);try{$refuse(fn()=>$workspace->workspace($enter('read')),403);}finally{config(['general_ledger.composition_enabled'=>true]);}$refuse(fn()=>$command('prepare','period-prepare',['period_key'=>'QA-2026-10','reason'=>'Unopened invoice, unposted supplier and unresolved cost must block joint conference.']));}); $case('sql-three-lines-only-for-invoice',function()use($ok){$original=(array)DB::table('gl_journals')->where('snapshot->source->effect_type','workshop.direct_cost.validated')->first();$proposal=(array)DB::table('gl_proposals')->where('id',$original['proposal_id'])->first();$review=(array)DB::table('gl_reviews')->where('id',$original['review_id'])->first();$snapshot=json_decode($original['snapshot'],true);$credit=$snapshot['lines'][1];$credit['credit_minor']=10000;$last=$credit;$last['credit_minor']=17500;$snapshot['lines']=[$snapshot['lines'][0],$credit,$last];$snapshot=Payables::canonical($snapshot);$key=hash('sha256','SQL-ONLY reviewed cost three lines');unset($proposal['id'],$review['id'],$original['id']);$proposal['effect_key']=$key;$proposal['snapshot']=$snapshot;$proposal['revision']=hash('sha256',$snapshot);$pid=DB::table('gl_proposals')->insertGetId($proposal);$review['proposal_id']=$pid;$review['revision']=$proposal['revision'];$rid=DB::table('gl_reviews')->insertGetId($review);$original['proposal_id']=$pid;$original['review_id']=$rid;$original['snapshot']=$snapshot;$original['effect_key']=$key;$jid=DB::table('gl_journals')->insertGetId($original);foreach(json_decode($snapshot,true)['lines'] as $i=>$line)DB::table('gl_lines')->insert(['tenant_id'=>$original['tenant_id'],'company_id'=>$original['company_id'],'unit_id'=>$original['unit_id'],'journal_id'=>$jid,'line_no'=>$i+1,'account_id'=>$line['account_id'],'debit_minor'=>$line['debit_minor'],'credit_minor'=>$line['credit_minor']]);$caught=false;DB::beginTransaction();try{DB::select('SELECT gl_assert_balanced(?)',[$jid]);}catch(Illuminate\Database\QueryException $e){$caught=str_contains($e->getMessage(),'GL_UNBALANCED_JOURNAL');}finally{DB::rollBack();}$ok($caught,'Reviewed balanced cost split into three matching lines rejected by SQL cardinality');}); $ok($before===$fingerprint(),'All rollback probes preserve original records, books, permissions and source state');file_put_contents($output,json_encode(['passed'=>true,'checks'=>$checks,'cases'=>$cases,'rollback_only'=>true,'private_synthetic_database_only'=>true,'preservation_verified'=>true],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo 'Composition regression: '.count($cases)." cases/$checks checks.\n";