'preview','order_id'=>$orderId,'revision'=>$cut['revision'],'reason'=>$cut['reason'],'data'=>$cut['data']]; $confirmation=['phase'=>'confirm','order_id'=>$orderId,'preview'=>$p['data']['preview']]; $checks=[];$ok=function($value,$name)use(&$checks,$proofRoot){if(!$value)throw new RuntimeException($name);$checks[]=$name;file_put_contents($proofRoot.'/security-progress.json',json_encode($checks));}; $beforeInvoices=$native->table('invoices')->orderBy('id')->get()->toJson();$beforeAudit=$native->table('audit_logs')->count(); $r=$send($confirmation,$key);$ok($r['status']===200,'existing confirmed invoice recovered without new business write');$invoice=$r['data']['invoice_id']; foreach(['tenant_id','company_id']as$field){$bad=$principal;$bad[$field]=999999;config(['sgc_invoice.principals.synthetic'=>$bad]);$ok($send($confirmation,$key)['status']===403,'foreign '.$field.' principal rejected');} $bad=$principal;$bad['enabled']=false;config(['sgc_invoice.principals.synthetic'=>$bad]);$ok($send($confirmation,$key)['status']===401,'disabled principal rejected even for replay'); $bad=$principal;$bad['token_sha256']=hash('sha256',str_repeat('r',64));config(['sgc_invoice.principals.synthetic'=>$bad]);$ok($send($confirmation,$key)['status']===401,'rotated credential invalidates old bearer'); $bad=$principal;$bad['context_version']=hash('sha256','new synthetic context');config(['sgc_invoice.principals.synthetic'=>$bad]); $ok($send($confirmation,$key)['status']===409,'old context header rejected after rotation'); $ok($send($confirmation,$key,['HTTP_X_SGC_CONTEXT'=>$bad['context_version']])['status']===409,'old preview rejected with new context header'); config(['sgc_invoice.principals.synthetic'=>$principal]); config(['modules.companies.'.$f['tenant'].':'.$f['company']=>['contracted'=>[],'enabled'=>[]]]); $ok($send($confirmation,$key)['status']===403,'disabled purchasing module refuses API replay');config(['modules.companies'=>[]]); $oldOrder=$native->table('purchase_orders')->where('tenant_id',$nativeFixture['tenant'])->where('id','<>',$orderId)->first(); $bad=$body;$bad['order_id']=(int)$oldOrder->id;$ok($send($bad,$key)['status']===409,'same key cannot be moved to another authorised order'); $ok($send($confirmation,strtoupper($key))['status']===200,'UUID case does not create a second operation'); $ok($send($body,$key,[], '/api/v1/integration/sgc/invoices?company_id=1')['status']===422,'query cannot inject another context'); $bad=$body;$bad['data']['items'][0]['tenant_id']=1;$ok($send($bad,$key)['status']===422,'nested unknown authority field rejected'); $bad=$body;$bad['phase']='validate';$ok($send($bad,$key)['status']===422,'transport cannot approve or consume invoice'); $ok($send($body,$key,[], '/api/v1/integration/sgc/payments')['status']===404,'legacy payment route remains unmounted'); $expired=$cut;$expired['observed']=time()-601;$old=Crypt::encryptString(json_encode($expired)); $ok($send(['phase'=>'confirm','order_id'=>$orderId,'preview'=>$old],$key)['status']===200,'durable receipt recovered after preview lifetime with current authority'); $expired['operation_key']=(string)Str::uuid();$old=Crypt::encryptString(json_encode($expired)); $ok($send(['phase'=>'confirm','order_id'=>$orderId,'preview'=>$old],$expired['operation_key'])['status']===409,'expired unapplied preview cannot write'); config(['database.connections.sgc_blocker'=>config('database.connections.'.DB::getDefaultConnection())]);$blocker=DB::connection('sgc_blocker'); file_put_contents($proofRoot.'/lock-job.json',json_encode(['body'=>$confirmation,'key'=>$key],JSON_THROW_ON_ERROR)); $worker=function(string $output)use($proofRoot,$repo){$p=new Symfony\Component\Process\Process([PHP_BINARY,__DIR__.'/sgc-invoice-proof.php','--worker','lock-job.json',$output],$repo,['SGC_INVOICE_PROOF_ROOT'=>$proofRoot],null,20);$p->run();if(!$p->isSuccessful())throw new RuntimeException('Lock worker failed');return json_decode(file_get_contents($proofRoot.'/'.$output),true);}; $blocker->beginTransaction();try{$blocker->select('SELECT pg_advisory_xact_lock(hashtextextended(?,0))',['sgc.invoice:'.$key]);$blocked=$worker('blocked.json');}finally{$blocker->rollBack();} $ok($blocked['status']===503&&($blocked['data']['error']??null)==='RETRY_SAME_KEY','lock timeout returns recoverable503 without duplicate'); $recovered=$worker('unblocked.json');$ok($recovered['status']===200&&$recovered['data']['invoice_id']===$invoice,'after lock release same operation recovers correct invoice'); $ok($beforeInvoices===$native->table('invoices')->orderBy('id')->get()->toJson()&&$beforeAudit===$native->table('audit_logs')->count(),'security and lock continuation added no invoices or audit commands'); $defaults=require $repo.'/config/sgc_invoice.php';$ok($defaults['enabled']===false&&$defaults['principals']===[],'source configuration remains disabled with no principals'); file_put_contents($proofRoot.'/security-result.json',json_encode(['passed'=>true,'checks'=>$checks,'new_business_rows'=>0,'lock_statuses'=>[$blocked['status'],$recovered['status']], 'base_proof_preserved_sha256'=>hash_file('sha256',$proofRoot.'/result.json'),'no_real_activation'=>true],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); echo json_encode(['passed'=>true,'checks'=>count($checks)]).PHP_EOL;