true]);$u=App\Models\User::findOrFail($f['actors']['read']);auth()->setUser($u);app(CompanyContext::class)->selectFor($u->id,$scope['tenant_id'],$scope['company_id'],$scope['unit_id']);$service=app(SupplierPayables::class); if($phase==='page-filter-positive'){ DB::beginTransaction();try{ $base=$service->document($u,$f['source_id']);unset($base['local_id']);$base['document']=999999;$base['number']='PENDING-RECOGNITION-FIXTURE';$payload=Payables::canonical($base);$id=DB::table('pa_imported_sources')->insertGetId($scope+['payload'=>$payload,'receipt_hash'=>hash('sha256',$payload)]);$visible=$service->listing($u,['q'=>'PENDING-RECOGNITION-FIXTURE','recognition'=>'unrecognised']);if($visible['pagination']['documents']['total']!==1||$visible['documents'][0]['local_id']!==$id||$visible['obligations']||!$visible['events']->isEmpty()||!$visible['proposals']->isEmpty())throw new RuntimeException('Unrecognised filter is not scoped before pagination');$absent=$service->listing($u,['q'=>'PENDING-RECOGNITION-FIXTURE','recognition'=>'recognised']);if($absent['pagination']['documents']['total']!==0)throw new RuntimeException('Recognised predicate mismatch'); $base['number']='INVISIBLE-SAME-COMPANY';$payload=Payables::canonical($base);$foreign=DB::table('pa_imported_sources')->insertGetId([...$scope,'unit_id'=>$scope['unit_id']+100,'payload'=>$payload,'receipt_hash'=>hash('sha256',$payload)]);if($service->listing($u,['q'=>'INVISIBLE-SAME-COMPANY'])['pagination']['documents']['total']!==0)throw new RuntimeException('Unit leak');try{$service->document($u,$foreign);throw new RuntimeException('Other-unit document accepted');}catch(Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e){if($e->getStatusCode()!==403)throw $e;} file_put_contents($s['root'].'/page-filter-positive.json',json_encode(['passed'=>true,'positive_unrecognised_document_visible'=>true,'recognised_filter_excludes_it'=>true,'other_unit_same_company_excluded'=>true,'no_other_evidence_returned'=>true,'test_rows_rolled_back'=>true],JSON_PRETTY_PRINT)); }finally{while(DB::transactionLevel()>0)DB::rollBack();}echo "Positive recognition filters and same-company other-unit isolation verified.\n";exit; } if($phase==='page-concurrent-read'){ $id=$service->listing($u)['documents'][0]['local_id'];if($id===$f['source_id'])throw new LogicException('Use a clone');$input=$s['root'].'/page-read-worker.json';file_put_contents($input,'{}');$process=null;DB::beginTransaction(); try{ DB::table('companies')->where('id',$scope['company_id'])->where('tenant_id',$scope['tenant_id'])->lockForUpdate()->firstOrFail();$row=DB::table('pa_source_histories')->where($scope)->where('local_source_id',$id)->first();$payload=json_decode($row->payload,true);$payload['receipt_version']=2;DB::table('pa_source_histories')->insert($scope+['local_source_id'=>$id,'version'=>2,'payload'=>Payables::canonical($payload),'receipt_hash'=>str_repeat('0',64),'created_at'=>now()]); $pipes=[];$process=proc_open([PHP_BINARY,__DIR__.'/payable-history-sgf-proof.php',$file,'page-read-worker',$input],[0=>['pipe','r'],1=>['file',$s['root'].'/page-read-worker-stdout.txt','w'],2=>['file',$s['root'].'/page-read-worker-stderr.txt','w']],$pipes,dirname(__DIR__));if(!is_resource($process))throw new RuntimeException('Worker failed');fclose($pipes[0]);$deadline=microtime(true)+8;do{$status=proc_get_status($process);if(!$status['running'])break;usleep(25000);}while(microtime(true)<$deadline);if($status['running'])throw new RuntimeException('Read waited for writer company lock');$exit=proc_close($process);$process=null;if($exit===-1)$exit=$status['exitcode'];if($exit!==0)throw new RuntimeException('Read worker failed');$result=json_decode(file_get_contents($input.'.result'),true);if($result['documents']!==25||count(array_unique($result['balances']))!==1||$result['balances'][0]!==3000||DB::transactionLevel()!==1)throw new RuntimeException('Read did not preserve committed snapshot'); file_put_contents($s['root'].'/page-concurrent-read.json',json_encode(['passed'=>true,'reader_completed_before_writer_release'=>true,'uncommitted_receipt_not_observed'=>true,'documents'=>25,'balance_minor'=>3000,'reader_time_ms'=>$result['time_ms'],'not_throughput_capacity'=>true],JSON_PRETTY_PRINT)); }finally{if(is_resource($process)){proc_terminate($process);proc_close($process);}while(DB::transactionLevel()>0)DB::rollBack();}echo "Page completed while writer held company lock; only committed receipt observed.\n";exit; } if($phase==='page-fresh-command'){ DB::beginTransaction();try{ $data=$service->listing($u);$id=$data['documents'][0]['local_id'];if($id===$f['source_id'])throw new LogicException('Use a benchmark clone, never the original workflow source');$row=DB::table('pa_imported_sources')->where($scope)->where('id',$id)->first();$doc=json_decode($row->payload,true,64,JSON_THROW_ON_ERROR);$doc['number']='CHANGED-AFTER-PAGE';DB::table('pa_imported_sources')->where('id',$id)->update(['payload'=>Payables::canonical($doc),'receipt_hash'=>hash('sha256',Payables::canonical($doc))]);DB::table('pa_access')->insert($scope+['user_id'=>$u->id,'action'=>'prepare','person'=>'sgf-history-person-'.$u->id]); try{$service->engine($u)->command('prepare_history',$id,'Synthetic conference after a read snapshot.',(string)Str::uuid());throw new RuntimeException('A read snapshot leaked into a command');}catch(DomainException $e){if(!str_contains($e->getMessage(),'Recibo histórico antigo'))throw $e;} file_put_contents($s['root'].'/page-fresh-command.json',json_encode(['passed'=>true,'read_cache_not_used_by_command'=>true,'current_document_and_history_anchor_revalidated'=>true,'test_changes_rolled_back'=>true],JSON_PRETTY_PRINT)); }finally{while(DB::transactionLevel()>0)DB::rollBack();}echo "Current source revalidated by command after a read page; no snapshot reuse.\n";exit; } DB::beginTransaction();DB::statement('SET TRANSACTION READ ONLY'); try{ $native=json_decode(file_get_contents($s['root'].'/source.json'),true,64,JSON_THROW_ON_ERROR)['source'];unset($native['local_id']);$original=DB::table('pa_imported_sources')->where($scope)->where('id',$f['source_id'])->first();if(Payables::canonical($native)!==Payables::canonical(json_decode($original->payload,true)))throw new LogicException('Original native receipt changed'); $counts=[];foreach(['pa_imported_sources','pa_sources','pa_proposals','pa_obligations','pa_history_imports'] as $table)$counts[$table]=DB::table($table)->where($scope)->count();$n=$counts['pa_imported_sources'];if(!in_array($n,[1000,5000,10000],true)||count(array_unique($counts))!==1||DB::table('pa_imported_payments')->where($scope)->count()!==3*$n||DB::getSchemaBuilder()->hasTable('pa_payment_decisions')||DB::getSchemaBuilder()->hasTable('ps_allocations'))throw new LogicException('Unexpected final synthetic ledger state'); if(DB::table('pa_access')->where($scope)->count()!==5)throw new LogicException('Temporary QA action was not restored'); $hash=hash_init('sha256');foreach(['pa_imported_sources','pa_source_histories','pa_sources','pa_proposals','pa_obligations','pa_history_imports','pa_imported_payments','pa_events','pa_commands','pa_access'] as $table){hash_update($hash,$table."\n");foreach(DB::table($table)->where($scope)->orderBy('id')->cursor() as $row)hash_update($hash,Payables::canonical((array)$row)."\n");} $report=['read_only'=>true,'original_workflow_receipt_unchanged'=>true,'counts'=>$counts,'imported_payments'=>3*$n,'temporary_decision_and_allocation_tables_absent'=>true,'scoped_business_fingerprint'=>hash_final($hash),'benchmark_clones'=>$n-1,'native_workflow_sources'=>1,'no_operational_installation'=>true]; $output=$s['root'].'/page-post.json';if(is_file($output))copy($output,$output.'.'.hash_file('sha256',$output).'.archive');file_put_contents($output,json_encode($report,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo json_encode($report)."\n"; }finally{DB::rollBack();}