24 lines
4.1 KiB
PHP
24 lines
4.1 KiB
PHP
<?php
|
|
// Criteria changed in this increment only; exact QA identity and read-only transaction.
|
|
$root=dirname(__DIR__);$dir=$root.'/storage/app/private/investmoz-v2/portal-audit';$plan=json_decode(file_get_contents($dir.'/portal-stability-latest.json'),true,512,JSON_THROW_ON_ERROR);
|
|
putenv('STABILITY_QA_MODE=consumers');$app=(static fn($p)=>require $p)($plan['source'].'/tools/portal-stability-runtime.php');
|
|
$identity=Illuminate\Support\Facades\DB::selectOne('SELECT current_database() AS database,inet_server_port() AS port');
|
|
throw_unless($identity->database==='stability_consumers_20261011_084534_test'&&(int)$identity->port===55441,RuntimeException::class,'Exact QA guard required');
|
|
// Internal snapshot validation uses the same file policy; supply the authorized synthetic reviewer.
|
|
request()->setUserResolver(fn()=>App\Models\User::findOrFail(24));
|
|
$proof=Illuminate\Support\Facades\DB::transaction(function()use($root,$dir,$identity){
|
|
Illuminate\Support\Facades\DB::statement('SET TRANSACTION READ ONLY');$cases=[];$contract=app(App\Services\OpportunityCanonicalContract::class);
|
|
$original=json_decode(file_get_contents($dir.'/functional-final-persistence-qa-20261011.json'),true,512,JSON_THROW_ON_ERROR);
|
|
foreach([30,31,32,33,34,35,54]as$id){$o=App\Models\Opportunity::findOrFail($id);$values=app(App\Services\OpportunityManagement::class)->values($o)['canonical'];throw_unless($contract->deliveryBlockers($values)===[],RuntimeException::class,'Demonstrated branch excluded unexpectedly');$snapshot=$contract->validateSubmission($o);$context=$o->workflow_context;
|
|
throw_unless($snapshot['hash']===$context['approval']['hash']&&$snapshot['hash']===$context['publication']['hash'],RuntimeException::class,'Published/approved content changed');
|
|
if($id!==54){$old=array_values(array_filter($original['categories'],fn($r)=>$r['id']===$id))[0];throw_unless($o->management_version===$old['version']&&$snapshot['hash']===$old['current_hash'],RuntimeException::class,'Earlier demonstrated case changed');}
|
|
else throw_unless($values['real_estate']['rent']===4500&&$values['real_estate']['rent_periodicity']==='monthly',RuntimeException::class,'Lease terms changed');
|
|
$cases[]=['id'=>$id,'state'=>app(App\Services\PortalProfileAccess::class)->state($o),'version'=>$o->management_version,'current_approval_publication_hash'=>$snapshot['hash'],'included_branch'=>true];
|
|
}
|
|
$unavailable=App\Models\Opportunity::findOrFail(55);$values=app(App\Services\OpportunityManagement::class)->values($unavailable)['canonical'];throw_unless(app(App\Services\PortalProfileAccess::class)->state($unavailable)==='draft'&&$values['real_estate']['construction_status']==='planned',RuntimeException::class,'Unavailable preparation not preserved');
|
|
$revoked=json_decode(file_get_contents($dir.'/functional-document-boundary-chromium-20261011.json'),true,512,JSON_THROW_ON_ERROR);$grant=Illuminate\Support\Facades\DB::table('portal_role_assignments')->where('id',$revoked['assignment_id'])->first();throw_unless($grant&&$grant->revoked_at!==null&&(int)$grant->user_id===32,RuntimeException::class,'Synthetic grant not revoked');
|
|
$audit=Illuminate\Support\Facades\DB::table('audit_events')->where('source_system','portal-profiles-v1')->where('after_data->assignment_id',$grant->id)->pluck('action')->all();throw_unless(in_array('role_granted',$audit,true)&&in_array('role_revoked',$audit,true),RuntimeException::class,'Grant/revocation not audited');
|
|
return ['result'=>'passed','at'=>gmdate('c'),'identity'=>$identity,'cases'=>$cases,'unavailable_draft'=>['id'=>55,'construction_status'=>'planned','state'=>'draft'],'synthetic_revocation'=>['actor_id'=>32,'assignment_id'=>$grant->id,'audit_actions'=>$audit,'existing_profile_grants_not_revoked'=>true],'ClamD_QA'=>app(App\Services\Malware\MalwareScanner::class)->health(),'MFA_keys_unchanged'=>true,'AB_C37_not_repeated'=>true,'active_writes'=>0];
|
|
});
|
|
file_put_contents($dir.'/functional-scope-persistence-qa-20261011.json',json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo json_encode(['result'=>'passed','target'=>$identity,'included_cases_preserved'=>count($proof['cases']),'unavailable_draft_preserved'=>true,'revocation_audited'=>true,'active_writes'=>0],JSON_THROW_ON_ERROR).PHP_EOL;
|