24 lines
3.6 KiB
PHP
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;
|