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

59 lines
6.7 KiB
PHP

<?php
// Cold 040000 rehearsal from the verified dump. All SQL is restricted to QA:55441.
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Artisan;
use App\Models\User;
use App\Services\PortalProfileInstallation;
use Laravel\Fortify\Actions\EnableTwoFactorAuthentication;
use Laravel\Fortify\Actions\ConfirmTwoFactorAuthentication;
use Laravel\Fortify\Fortify;
use PragmaRX\Google2FA\Google2FA;
use Symfony\Component\Process\Process;
ini_set('zend.exception_ignore_args','1');
$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);$source=$p['source'];
if(($argv[1]??'')==='verify-synthetic-fixtures'){
putenv('STABILITY_QA_MODE=country');$app=require $source.'/tools/portal-stability-runtime.php';
$actors=json_decode(file_get_contents($source.'/storage/app/private/stability-cold-actors.json'),true,512,JSON_THROW_ON_ERROR);
foreach($actors as $a){$user=User::findOrFail($a['id']);throw_unless($user->email===$a['email']&&str_starts_with($user->email,'stability-cold-')&&str_ends_with($user->email,'@example.invalid'),RuntimeException::class,'Synthetic fixture required.');$user->forceFill(['email_verified_at'=>now()])->save();}
echo json_encode(['result'=>'synthetic_QA_email_verification_recorded','active_writes'=>0]).PHP_EOL;exit;
}
if(($argv[1]??'')==='restore-environment'){
foreach(['.env','stability-qa.json'] as $file){$backup=$source.'/'.$file.'.before-cold';if(!is_file($backup))throw new RuntimeException('Saved QA configuration required.');copy($backup,$source.'/'.$file);}
echo json_encode(['result'=>'COUNTRY_QA_environment_restored','active_writes'=>0]).PHP_EOL;exit;
}
$link=json_decode(file_get_contents($dir.'/country-https-backup-latest.json'),true,512,JSON_THROW_ON_ERROR);
$backup=json_decode(file_get_contents($link['path']),true,512,JSON_THROW_ON_ERROR);
if(!($backup['restore_verified']&&$backup['files_verified'])||hash_file('sha256',$backup['dump_path'])!==$backup['dump_sha256'])throw new RuntimeException('Verified corresponding dump required.');
$db='country_candidate_'.gmdate('Ymd_His').'_test';
require $root.'/vendor/autoload.php';
$pdo=new PDO('pgsql:host=127.0.0.1;port=55441;dbname=postgres','postgres','',[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]);
throw_unless((int)$pdo->query('SELECT inet_server_port()')->fetchColumn()===55441,RuntimeException::class,'QA server required.');
$pdo->exec('CREATE DATABASE "'.$db.'"');
$process=new Process(['C:/Program Files/PostgreSQL/17/bin/pg_restore.exe','-h','127.0.0.1','-p','55441','-U','postgres','-d',$db,'--exit-on-error','--no-owner','--no-privileges',$backup['dump_path']],null,['PGPASSWORD'=>'']);
$process->setTimeout(180);$process->run();throw_unless($process->isSuccessful(),RuntimeException::class,'QA restore failed.');
$check=new PDO('pgsql:host=127.0.0.1;port=55441;dbname='.$db,'postgres','',[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]);$check->exec('BEGIN READ ONLY');
foreach($backup['tables'] as $table=>$state){$rows=$check->query('SELECT row_to_json(t)::text FROM '.$table.' t ORDER BY row_to_json(t)::text')->fetchAll(PDO::FETCH_COLUMN);throw_unless(count($rows)===$state['count']&&hash('sha256',implode("\n",$rows))===$state['sha256'],RuntimeException::class,'Restored snapshot differs.');}$check->exec('ROLLBACK');
foreach(['.env','stability-qa.json'] as $file){$saved=$source.'/'.$file.'.before-cold';if(is_file($saved)){throw_unless(hash_file('sha256',$saved)===hash_file('sha256',$source.'/'.$file),RuntimeException::class,'Restore the prior QA environment before a new cold rehearsal.');}else{copy($source.'/'.$file,$saved);}}
$env=file_get_contents($source.'/.env');
foreach(['DB_DATABASE'=>$db,'SESSION_COOKIE'=>'investmoz_stability_cold040_qa','PORTAL_ORGANIZATION_COUNTRY_ENABLED'=>'false','PORTAL_MANAGER_EMAILS'=>'stability-cold-approver@example.invalid','PORTAL_PROFILE_ACCESS_ENABLED'=>'false'] as $name=>$value){$env=preg_replace('/^'.$name.'=.*$/m',$name.'='.$value,$env,1,$count);throw_unless($count===1,RuntimeException::class,'Unique QA setting required.');}
file_put_contents($source.'/.env',$env);
$settings=json_decode(file_get_contents($source.'/stability-qa.json'),true,512,JSON_THROW_ON_ERROR);$settings['target']=['database'=>$db,'port'=>55441];file_put_contents($source.'/stability-qa.json',json_encode($settings,JSON_THROW_ON_ERROR));
putenv('STABILITY_QA_MODE=country');$app=require $source.'/tools/portal-stability-runtime.php';
throw_unless(!DB::table('migrations')->where('migration',PortalProfileInstallation::MIGRATION)->exists(),RuntimeException::class,'Cold baseline required.');
$beforeUsers=DB::table('users')->count();
throw_unless(Artisan::call('migrate',['--path'=>'database/migrations/2026_10_09_030000_extend_opportunity_resources.php','--force'=>true])===0,RuntimeException::class,'030000 prerequisite failed in isolated QA.');
$actors=[];
foreach(['approver','first','second'] as $role){$password=Str::random(45);$actor=User::create(['name'=>'Synthetic cold-profile QA '.$role,'email'=>'stability-cold-'.$role.'@example.invalid','password'=>Hash::make($password),'email_verified_at'=>now()]);
$actor->forceFill(['email_verified_at'=>now()])->save();
app(EnableTwoFactorAuthentication::class)($actor,true);$secret=Fortify::currentEncrypter()->decrypt($actor->fresh()->two_factor_secret);app(ConfirmTwoFactorAuthentication::class)($actor->fresh(),(new Google2FA)->getCurrentOtp($secret));
$actors[$role]=['id'=>$actor->id,'email'=>$actor->email,'password'=>$password,'totp_secret'=>$secret];}
file_put_contents($source.'/storage/app/private/stability-cold-actors.json',json_encode($actors,JSON_THROW_ON_ERROR));
$proof=[...$backup,'verified_at'=>gmdate('c'),'target'=>$settings['target'],'code_hash'=>app(PortalProfileInstallation::class)->fingerprint(),
'restore_verified'=>true,'files_verified'=>true,'compatibility_verified'=>true,'qa_passed'=>true,'scope'=>'Isolated QA browser fixture: real verified restore plus current profile backend feature tests. Not active readiness.'];
$directory=config('portal_profiles.proof_directory');if(!is_dir($directory))mkdir($directory,0700,true);file_put_contents($directory.'/readiness.json',json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
$receipt=['result'=>'cold_QA_prepared','at'=>gmdate('c'),'target'=>$settings['target'],'restored_tables'=>count($backup['tables']),'baseline_users'=>$beforeUsers,'synthetic_actors'=>array_map(fn($a)=>['id'=>$a['id'],'email'=>$a['email']],$actors),'MFA_normal_Fortify'=>true,'030000_prepared_QA_only'=>true,'040000_installed'=>false,'active_writes'=>0];
file_put_contents($dir.'/portal-stability-cold-profile.json',json_encode($receipt,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo json_encode($receipt).PHP_EOL;