Files
Investidor-V2/tools/portal-functional-conditions-qa.php
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

24 lines
3.6 KiB
PHP

<?php
// Semantic contract checks using real isolated resources; all mutations are in-memory.
use App\Models\Opportunity;
use App\Models\User;
use App\Services\OpportunityCanonicalContract;
use App\Services\OpportunityReviewConditions;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
$root=dirname(__DIR__);$dir=$root.'/storage/app/private/investmoz-v2/portal-audit';$p=json_decode(file_get_contents($dir.'/portal-stability-latest.json'),true,512,JSON_THROW_ON_ERROR);
putenv('STABILITY_QA_MODE=consumers');$app=require $p['source'].'/tools/portal-stability-runtime.php';
$proof=DB::transaction(function():array {
DB::statement('SET TRANSACTION READ ONLY');$record=Opportunity::findOrFail(31);$snapshot=app(OpportunityCanonicalContract::class)->validateSubmission($record);$service=app(OpportunityReviewConditions::class);$actor=User::findOrFail(24);$doc=array_key_first($snapshot['resources']['documents']);$context=[];
$data=['gate'=>'registry_urban_review','gate_decision'=>'approved','evidence_document_ids'=>[$doc],'reason'=>'Synthetic QA verification with traceable existing evidence.','condition'=>['description'=>'Synthetic QA evidence condition','responsible_user_id'=>21,'due_on'=>null,'blocking_action'=>'approve']];
$service->review($record,$actor,$data,$snapshot,$context);$id=array_key_first($context['conditions']);$condition=$context['conditions'][$id];throw_unless($condition['due_on']===null&&$condition['status']==='open',RuntimeException::class,'No implicit date or resolution.');
$deny=static function(callable $operation):void {try{$operation();}catch(ValidationException){return;}throw new RuntimeException('Expected controlled field validation.');};
$deny(fn()=>$service->authorize($context,$snapshot,'approve'));$deny(fn()=>$service->authorize($context,$snapshot,'publish'));
$invalid=$data;$invalid['condition']['responsible_user_id']=23;$unused=[];$deny(function() use($service,$record,$actor,$invalid,$snapshot,&$unused){$service->review($record,$actor,$invalid,$snapshot,$unused);});
$resolve=$data;unset($resolve['condition']);$resolve['resolve_condition_ids']=[$id];$service->review($record,$actor,$resolve,$snapshot,$context);$service->authorize($context,$snapshot,'approve');$service->authorize($context,$snapshot,'publish');
$wrong=$resolve;$wrong['gate']='building_compliance_review';$deny(function()use($service,$record,$actor,$wrong,$snapshot,&$context){$service->review($record,$actor,$wrong,$snapshot,$context);});
$changed=$snapshot;$changed['resources']['documents'][$doc]['sha256']=str_repeat('b',64);$deny(fn()=>$service->authorize($context,$changed,'publish'));$service->reconcile($context,$changed,[]);throw_unless($context['conditions'][$id]['status']==='open'&&count($context['conditions'][$id]['resolution_history'])===1,RuntimeException::class,'Changed evidence must reopen only its condition and preserve history.');
$publication=[];$data['condition']['blocking_action']='publish';$service->review($record,$actor,$data,$snapshot,$publication);$service->authorize($publication,$snapshot,'approve');$deny(fn()=>$service->authorize($publication,$snapshot,'publish'));
return ['result'=>'passed','at'=>gmdate('c'),'in_memory_only'=>true,'checks'=>['no_implicit_deadline','open_condition_blocks_selected_actions','unauthorized_responsible_rejected','resolved_with_own_clean_evidence','wrong_gate_resolution_rejected','changed_evidence_reopens_condition_preserving_history','publication_condition_allows_internal_approval_only'],'active_writes'=>0];
});file_put_contents($dir.'/functional-conditions-semantic-qa-20261011.json',json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo json_encode($proof,JSON_THROW_ON_ERROR).PHP_EOL;