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

53 lines
4.5 KiB
PHP

<?php
// Reproduce the existing membership scope in QA only; discard all fixtures afterwards.
ini_set('zend.exception_ignore_args', '1');
$root = dirname(__DIR__);
$private = $root.'/storage/app/private/investmoz-v2/portal-audit';
$plan = json_decode(file_get_contents($private.'/onboarding-governance-plan.json'),true,512,JSON_THROW_ON_ERROR);
$stage = realpath($plan['source']);
if (!($stage && str_starts_with(strtolower($stage),strtolower(realpath($private).DIRECTORY_SEPARATOR)) && $plan['target']['port']===55441)) {
throw new RuntimeException('Separate QA source required.');
}
require $stage.'/qa-autoload.php';
$app = require $stage.'/bootstrap/app.php';
(new Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables)->bootstrap($app);
(new Illuminate\Foundation\Bootstrap\LoadConfiguration)->bootstrap($app);
$c=config('database.connections.'.config('database.default'));
throw_unless(config('app.env')==='testing' && $c['driver']==='pgsql' && empty($c['url']) && (int)$c['port']===55441 && $c['database']===$plan['target']['database'] && str_ends_with($c['database'],'_test') && config('mail.default')==='array',RuntimeException::class,'QA environment refused.');
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
throw_unless(str_starts_with((new ReflectionClass(App\Services\PortalProfileAccess::class))->getFileName(),$stage),RuntimeException::class,'Active classes refused.');
$identity=DB::selectOne('SELECT current_database() AS database,inet_server_port() AS port');
throw_unless((int)$identity->port===55441 && $identity->database===$plan['target']['database'],RuntimeException::class,'QA database refused.');
DB::beginTransaction();
try {
$before=[];foreach(['users','organizations','memberships'] as $t)$before[$t]=DB::table($t)->count();
$actor=App\Models\User::factory()->create();
$organization=(string)Illuminate\Support\Str::uuid();
DB::table('organizations')->insert(['id'=>$organization,'name'=>'Synthetic portal business scope QA','organization_type'=>'private']);
$membership=(string)Illuminate\Support\Str::uuid();
DB::table('memberships')->insert(['id'=>$membership,'user_id'=>$actor->id,'organization_id'=>$organization,'role'=>'officer']);
$access=app(App\Services\PortalProfileAccess::class);
$country=app(App\Services\OrganizationCountry::class);
$desk=app(App\Services\VirtualDesk::class);
$proof=['at'=>gmdate('c'),'target'=>$identity,'QA_only'=>true,'source'=>'User clarification: Aurora acts within portal business, not company management',
'requested_scope'=>'promoter_portal_business_only','synthetic_fixtures'=>true,'active_writes'=>0,'real_organization_or_accounts_created'=>false];
foreach(['officer','viewer'] as $role){
DB::table('memberships')->where('id',$membership)->update(['role'=>$role]);
$allowed=true;
try{$country->authorize($actor,$organization,true);}catch(Symfony\Component\HttpKernel\Exception\HttpException $e){throw_unless($e->getStatusCode()===403,RuntimeException::class);$allowed=false;}
$proof['existing_roles'][$role]=['promoter_representation_allowed'=>$access->represents($actor,$organization),
'master_country_write_authorized'=>$allowed,'organizational_desk_write_authorized'=>$desk->represents($actor,$organization,true),
'opportunity_operational_flag'=>(bool)config('portal.profile_access_enabled')];
}
throw_unless($proof['existing_roles']['officer']['promoter_representation_allowed'] && $proof['existing_roles']['officer']['master_country_write_authorized']
&& $proof['existing_roles']['officer']['organizational_desk_write_authorized'] && !$proof['existing_roles']['viewer']['promoter_representation_allowed'],RuntimeException::class,'Existing behavior differs; review required.');
DB::rollBack();
foreach($before as $t=>$n)throw_unless(DB::table($t)->count()===$n,RuntimeException::class,'QA fixture not rolled back.');
$proof['QA_fixtures_rolled_back']=true;
$proof['result']='existing_scope_coupling_demonstrated_not_corrected';
$proof['correction_required']='Distinguish portal-business representation and employment from company master/general dossier write; do not assign officer/manager/admin as a shortcut.';
file_put_contents($private.'/tempo-scope-diagnosis-qa.json',json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
echo json_encode($proof,JSON_THROW_ON_ERROR).PHP_EOL;
} catch(Throwable $e){if(DB::transactionLevel()>0)DB::rollBack();fwrite(STDERR,'QA diagnosis incomplete; no active writes; '.$e::class);exit(1);}