require $p)(__DIR__.'/portal-service-followup-runtime.php'); $db = Illuminate\Support\Facades\DB::connection(); $row = $db->table('portal_security_approvals')->where('kind','bootstrap')->where('requested_by',15)->where('subject_user_id',16)->first(); throw_unless($row && $row->consumed_at, RuntimeException::class); $installation = app(App\Services\PortalProfileInstallation::class); $second = App\Models\User::findOrFail(16); $session = app('session')->driver();$session->start();$session->forget(['portal.mfa_actor','portal.mfa_at']); $pairBefore = $db->table('portal_superuser_pair')->first(); $auditBefore = $db->table('audit_events')->count(); $denied = false; try { $installation->confirmBootstrap($second,$row->id,['hash'=>$installation->bootstrapPreview($second,$row->id)['hash'], 'confirm'=>true,'idempotency_key'=>(string)Illuminate\Support\Str::uuid(),'reason'=>'SIMULAÇÃO QA: uma sessão sem MFA recente nunca confirma nem recupera a operação protegida.']); } catch (Symfony\Component\HttpKernel\Exception\HttpException $error) { $denied = $error->getStatusCode() === 403; } throw_unless($denied && $pairBefore == $db->table('portal_superuser_pair')->first() && $auditBefore === $db->table('audit_events')->count(), RuntimeException::class,'Missing MFA must deny before side effects'); $proof=['result'=>'passed','scope'=>'Service security check without recent MFA; browser normal-MFA ceremony is proved separately','status'=>403,'pair_unchanged'=>true,'audit_unchanged'=>true,'active_writes'=>0]; file_put_contents(dirname(__DIR__).'/storage/app/private/investmoz-v2/portal-audit/service-followup-bootstrap-mfa-negative-qa.json',json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); echo json_encode($proof,JSON_THROW_ON_ERROR).PHP_EOL;