getMessage().PHP_EOL);exit(1); }); $app=require $root.'/bootstrap/app.php';(new LoadEnvironmentVariables)->bootstrap($app);(new LoadConfiguration)->bootstrap($app); $dir=$root.'/storage/app/private/investmoz-v2/portal-audit'; $read=static fn($p)=>json_decode(file_get_contents($p),true,512,JSON_THROW_ON_ERROR); $prepared=$read($dir.'/stability-active-preparation-latest.json'); $proof=$read($read($dir.'/stability-active-backup-latest.json')['path']); $before=$proof; $before['counts']=[]; foreach(['users','organizations','memberships','migrations','audit_events'] as $table){$before['counts'][$table]=$proof['tables']['"public"."'.$table.'"']['count'];} throw_unless($proof['delivery_revision']==='485ee04c40b2754ab668f48fd84d8559fb19a8b98f4b9af50fc0517bb488ca76',RuntimeException::class,'Exact authorized revision required.'); $manifest=$read($root.'/outputs/investmoz-portal-stability-20261011/manifesto-candidata.json'); $mode=$argv[1] ?? 'before-apply';throw_unless(in_array($mode,['before-apply','installed-disabled','enabled','reverted'],true),RuntimeException::class,'Unknown phase.'); $expectedFingerprint=$mode==='reverted'?$before['source_code_hash']:$before['code_hash']; throw_unless((new OrganizationCountryInstallation)->fingerprint()===$expectedFingerprint,RuntimeException::class,'Active code differs from expected phase.'); $c=config('database.connections.'.config('database.default')); throw_unless($c['driver']==='pgsql' && empty($c['url']) && (int)$c['port']===5432 && $c['database']==='investemoz',RuntimeException::class,'Exact target required.'); $key=config('app.key');$zip=new ZipArchive;throw_unless($zip->open($proof['files_path'])===true,RuntimeException::class,'Backup unavailable.'); $runtime=json_decode($zip->getFromName('runtime/effective-runtime.json'),true,512,JSON_THROW_ON_ERROR);$zip->close(); throw_unless($runtime['app_key']===$key && $runtime['cipher']===config('app.cipher'),RuntimeException::class,'Encryption key/cipher changed.'); $key=str_starts_with($key,'base64:')?base64_decode(substr($key,7),true):$key;$crypt=new Encrypter($key,config('app.cipher')); if($mode!=='reverted') { throw_unless(config('app.url')==='https://portal-investidor.test' && config('session.cookie')==='portal_investidor_https' && config('session.secure')===true && config('session.domain')===null && config('session.path')==='/' && config('session.same_site')==='lax',RuntimeException::class,'Effective HTTPS/session config differs.'); } else { $stage=$read($dir.'/stability-active-stage-latest.json'); foreach($stage['backup_files'] as $file=>$entry){throw_unless(hash_file('sha256',$file)===$entry['sha256'],RuntimeException::class,'Reversed file differs from snapshot.');} } if($mode!=='reverted'){ foreach($manifest['revision_input']['application_files'] as $file=>$entry){throw_unless(hash_file('sha256',$root.'/'.$file)===$entry['after'],RuntimeException::class,'Authorized application member differs.');} foreach($manifest['revision_input']['assets'] as $file=>$digest){throw_unless(hash_file('sha256',$root.'/public/build/'.$file)===$digest,RuntimeException::class,'Authorized production member differs.');} throw_unless(hash_file('sha256',$prepared['dll'])===$manifest['revision_input']['deployment_files']['runtime/nghttp2.dll'],RuntimeException::class,'Shared runtime DLL differs.'); throw_unless(hash_file('sha256',($read($dir.'/stability-active-stage-latest.json')['effective_vhost_path']??$prepared['active_vhost']))===$manifest['revision_input']['deployment_files']['portal-investidor.test-https.proposta.conf'],RuntimeException::class,'HTTPS vhost differs.'); } $flags=[];foreach(['opportunity_dashboard_access_enabled','profile_access_enabled','opportunity_specialized_drafts_enabled','opportunity_modular_profiles_qa_enabled','legacy_content_qa_enabled'] as $flag){$flags[$flag]=(bool)config('portal.'.$flag);throw_if($flags[$flag],RuntimeException::class,'Unapproved flag enabled.');} $flags['investor_path_enabled']=(bool)config('investor-path.enabled');throw_if($flags['investor_path_enabled'],RuntimeException::class,'Unapproved investor path flag enabled.'); $enabled=(bool)config('portal.organization_country_enabled');throw_unless($enabled===($mode==='enabled'),RuntimeException::class,'Country flag differs from phase.'); $pdo=new PDO('pgsql:host='.$c['host'].';port=5432;dbname=investemoz',$c['username'],$c['password'],[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]); $pdo->exec('BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY'); throw_unless($pdo->query('SELECT current_database()')->fetchColumn()==='investemoz' && (int)$pdo->query('SELECT inet_server_port()')->fetchColumn()===5432,RuntimeException::class,'Server identity differs.'); $tables=[];$changed=[]; foreach($pdo->query("SELECT schemaname,tablename FROM pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema') ORDER BY schemaname,tablename")->fetchAll(PDO::FETCH_ASSOC) as $t){ $name='"'.str_replace('"','""',$t['schemaname']).'"."'.str_replace('"','""',$t['tablename']).'"'; $rows=$pdo->query('SELECT row_to_json(t)::text FROM '.$name.' t ORDER BY row_to_json(t)::text')->fetchAll(PDO::FETCH_COLUMN); $tables[$name]=['count'=>count($rows),'sha256'=>hash('sha256',implode("\n",$rows))];if(($before['tables'][$name]??null)!==$tables[$name])$changed[]=$name; } throw_unless(array_keys($tables)===array_keys($before['tables']),RuntimeException::class,'A table was created/removed.'); $allowed=['"public"."sessions"','"public"."cache"','"public"."cache_locks"']; if(!in_array($mode,['before-apply','reverted'],true))$allowed=[...$allowed,'"public"."migrations"','"public"."audit_events"']; $authenticationMetadata=[]; if($mode==='enabled' && in_array('"public"."users"',$changed,true)){ // Fortify's normal logout cycles remember_token. Compare every other field to the verified original clone. $cloneTarget=$proof['restored_target'];throw_unless((int)$cloneTarget['port']===55441 && preg_match('/^country_candidate_\d{8}_\d{6}_test$/',$cloneTarget['database']),RuntimeException::class,'Original clone identity differs.'); $original=new PDO('pgsql:host=127.0.0.1;port=55441;dbname='.$cloneTarget['database'],'postgres','',[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]);$original->exec('BEGIN READ ONLY'); $userSql='SELECT row_to_json(t)::text FROM users t ORDER BY row_to_json(t)::text';$originalRows=$original->query($userSql)->fetchAll(PDO::FETCH_COLUMN);$original->exec('ROLLBACK'); throw_unless(hash('sha256',implode("\n",$originalRows))===$before['tables']['"public"."users"']['sha256'],RuntimeException::class,'Original clone users differ from snapshot.'); $index=static function(array $rows):array{$out=[];foreach($rows as $row){$user=json_decode($row,true,512,JSON_THROW_ON_ERROR);$out[$user['id']]=$user;}ksort($out);return $out;}; $oldUsers=$index($originalRows);$newUsers=$index($pdo->query($userSql)->fetchAll(PDO::FETCH_COLUMN)); throw_unless(array_keys($oldUsers)===array_keys($newUsers),RuntimeException::class,'Identity set changed.'); $actors=$pdo->query("SELECT DISTINCT actor_user_id FROM audit_events WHERE source_system='organization-country-installation'")->fetchAll(PDO::FETCH_COLUMN); $observedBrowser=$read($dir.'/stability-active-browser-status.json'); throw_unless(count(array_filter($observedBrowser['navigation'],static fn($r)=>$r['path']==='/logout' && $r['method']==='POST' && in_array($r['status'],[302,303],true)))>0,RuntimeException::class,'Actual normal logout not demonstrated.'); foreach($oldUsers as $id=>$oldUser){$newUser=$newUsers[$id];if($oldUser!==$newUser){throw_unless(in_array($id,$actors),RuntimeException::class,'Unrelated identity changed.');$originalToken=$oldUser['remember_token'];$newToken=$newUser['remember_token'];unset($oldUser['remember_token'],$newUser['remember_token']);throw_unless($oldUser===$newUser && $originalToken!==$newToken,RuntimeException::class,'User field other than normal logout token changed.');unset($originalToken,$newToken);$authenticationMetadata[]=['user_id'=>$id,'changed_fields'=>['remember_token'],'cause'=>'Laravel SessionGuard logout cycles the existing remember token; all other identity fields unchanged.'];}} $allowed[]='"public"."users"'; } $unexpected=array_values(array_diff($changed,$allowed)); if($unexpected!==[]){file_put_contents($dir.'/stability-active-unexpected-row-changes.json',json_encode(['at'=>gmdate('c'),'phase'=>$mode,'tables'=>$unexpected,'SQL_readonly'=>true,'row_values_or_secrets_exported'=>false],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));} throw_unless($unexpected===[],RuntimeException::class,'Business rows changed outside reviewed effects.'); $counts=[];foreach(array_keys($before['counts']) as $table)$counts[$table]=(int)$pdo->query('SELECT count(*) FROM "'.$table.'"')->fetchColumn(); foreach(['users','organizations','memberships'] as $table)throw_unless($counts[$table]===$before['counts'][$table],RuntimeException::class,'An identity/organization/membership was created or removed.'); $migrations=$pdo->query("SELECT migration FROM migrations WHERE migration IN ('2026_10_09_030000_extend_opportunity_resources','2026_10_10_040000_create_portal_profile_authorization','2026_10_09_190000_prepare_investor_path','2026_10_10_050000_extend_organization_country') ORDER BY migration")->fetchAll(PDO::FETCH_COLUMN); $columns=$pdo->query("SELECT column_name,data_type,is_nullable,character_maximum_length FROM information_schema.columns WHERE table_schema='public' AND table_name='organizations' AND column_name IN ('incorporation_country_code','incorporation_country_provenance') ORDER BY column_name")->fetchAll(PDO::FETCH_ASSOC); $audits=$pdo->query("SELECT id,created_at,actor_user_id,correlation_id,after_data FROM audit_events WHERE source_system='organization-country-installation' ORDER BY created_at,id")->fetchAll(PDO::FETCH_ASSOC); if(in_array($mode,['before-apply','reverted'],true)){throw_unless($migrations===[] && $columns===[] && $audits===[],RuntimeException::class,'Unexpected installation before authenticated action.');} else { throw_unless($migrations===[OrganizationCountryInstallation::MIGRATION] && count($columns)===2 && count($audits)===1,RuntimeException::class,'Installation effects differ.'); throw_unless($columns===[['column_name'=>'incorporation_country_code','data_type'=>'character varying','is_nullable'=>'YES','character_maximum_length'=>2],['column_name'=>'incorporation_country_provenance','data_type'=>'jsonb','is_nullable'=>'YES','character_maximum_length'=>null]],RuntimeException::class,'Country column contracts differ.'); throw_unless($counts['migrations']===$before['counts']['migrations']+1 && $counts['audit_events']===$before['counts']['audit_events']+1,RuntimeException::class,'Ledger/audit count differs.'); $receipt=json_decode($audits[0]['after_data'],true,512,JSON_THROW_ON_ERROR);throw_unless($receipt['code_hash']===$before['code_hash'] && $receipt['result']['new_columns']===2 && $receipt['result']['new_tables']===0 && $receipt['result']['new_organizations']===0,RuntimeException::class,'Audited receipt differs.'); } $recovered=0;foreach($pdo->query('SELECT two_factor_secret FROM users WHERE two_factor_secret IS NOT NULL')->fetchAll(PDO::FETCH_COLUMN) as $encrypted){$v=$crypt->decrypt($encrypted,false);throw_unless(is_string($v)&&strlen($v)>0,RuntimeException::class,'Original MFA unreadable.');unset($v);$recovered++;} $sequenceSql="SELECT * FROM pg_sequences WHERE schemaname NOT IN ('pg_catalog','information_schema') ORDER BY schemaname,sequencename"; $sequences=$pdo->query($sequenceSql)->fetchAll(PDO::FETCH_ASSOC); $expectedSequences=$proof['sequences']; if(in_array($mode,['installed-disabled','enabled'],true)){ foreach($expectedSequences as &$sequence){if($sequence['schemaname']==='public' && $sequence['sequencename']==='migrations_id_seq'){$sequence['last_value']++;}}unset($sequence); } throw_unless($sequences===$expectedSequences,RuntimeException::class,'Unapproved sequence change.'); $pdo->exec('ROLLBACK'); $result=['result'=>'passed','at'=>gmdate('c'),'phase'=>$mode,'code_hash'=>$expectedFingerprint,'prepared_code_hash'=>$before['code_hash'],'delivery_revision'=>$before['delivery_revision'], 'origin'=>config('app.url'),'country_enabled'=>$enabled,'other_flags'=>$flags,'tables'=>count($tables),'counts_before'=>$before['counts'],'counts_after'=>$counts, 'changed_tables'=>$changed,'business_rows_preserved'=>true,'columns'=>$columns,'installed_packages'=>$migrations,'installation_audits'=>count($audits), 'authentication_metadata_changes'=>$authenticationMetadata, 'original_mfa_envelopes_recovered'=>$recovered,'key_and_cipher_preserved'=>true,'active_SQL_writes_by_verifier'=>0, 'installation_audit_reference'=>array_map(static fn($audit)=>array_intersect_key($audit,array_flip(['id','created_at','actor_user_id','correlation_id'])),$audits), 'actual_master_save_available'=>$counts['organizations']>0 && $counts['memberships']>0, 'master_save_limitation'=>$counts['organizations']===0?'No real organization or membership; active master write/reuse cannot be demonstrated without separately authorized legitimate master data.':null]; file_put_contents($dir.'/stability-active-check-'.$mode.'-20261011.json',json_encode($result,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo json_encode($result,JSON_THROW_ON_ERROR).PHP_EOL;