getMessage().PHP_EOL); exit(1); }); $read = static fn ($p) => json_decode(file_get_contents($p), true, 512, JSON_THROW_ON_ERROR); $private = $root.'/storage/app/private/investmoz-v2/portal-audit'; $out = $root.'/outputs/investmoz-country02-https-20261011'; $manifest = $read($out.'/manifesto-candidata.json'); $sealed = $read($out.'/manifesto-pacote.json'); throw_unless($manifest['code_hash'] === '162daff6ce08117582dd7d796639d02b156d1b940cd85ef3587ff88a65747edd' && $manifest['delivery_revision'] === '13644ed74a48b69767ae3f0759a1adb430b7ba982169d2aaf409363429276709', RuntimeException::class, 'Authorized replacement differs.'); throw_unless(hash_file('sha256', $out.'/manifesto-candidata.json') === $sealed['manifesto_candidata_sha256'] && hash_file('sha256', $out.'/'.$sealed['archive']) === $sealed['archive_sha256'], RuntimeException::class, 'Sealed package differs.'); $proof = $read($read($private.'/country-https-backup-latest.json')['path']); throw_unless($proof['code_hash'] === $manifest['code_hash'] && $proof['production_manifest_sha256'] === $manifest['production']['manifest_sha256'] && strtotime($proof['verified_at']) >= time()-86400, RuntimeException::class, 'Corresponding backup expired or differs.'); foreach (['restore_verified','files_verified','sequences_verified','compatibility_verified','reversal_verified','qa_passed'] as $key) { throw_unless($proof[$key] === true, RuntimeException::class, 'Incomplete restore/QA evidence.'); } throw_unless(hash_file('sha256', $proof['dump_path']) === $proof['dump_sha256'] && hash_file('sha256', $proof['files_path']) === $proof['files_sha256'], RuntimeException::class, 'Backup bytes differ.'); $app = require $root.'/bootstrap/app.php'; (new LoadEnvironmentVariables)->bootstrap($app); (new LoadConfiguration)->bootstrap($app); $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 active target required.'); throw_unless(!config('portal.organization_country_enabled') && !$app->configurationIsCached(), RuntimeException::class, 'Disabled flag/uncached baseline required.'); $zip = new ZipArchive; throw_unless($zip->open($proof['files_path']) === true, RuntimeException::class, 'Restore archive unreadable.'); $archived = json_decode($zip->getFromName('runtime/effective-runtime.json'), true, 512, JSON_THROW_ON_ERROR); throw_unless($archived['app_key'] === config('app.key') && $archived['cipher'] === config('app.cipher') && $zip->getFromName('runtime/.env') === file_get_contents($root.'/.env'), RuntimeException::class, 'Stable key/environment differs.'); $zip->close(); $key = config('app.key'); $key = str_starts_with($key, 'base64:') ? base64_decode(substr($key, 7), true) : $key; $crypt = new Encrypter($key, config('app.cipher')); $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'); $identity = $pdo->query("SELECT current_database() AS database,inet_server_port() AS port,current_setting('transaction_read_only') AS read_only")->fetch(PDO::FETCH_ASSOC); throw_unless($identity['database'] === 'investemoz' && (int)$identity['port'] === 5432 && $identity['read_only'] === 'on', RuntimeException::class, 'Actual target 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 (($proof['tables'][$name] ?? null) !== $tables[$name]) $changed[]=$name; } throw_unless(array_keys($tables) === array_keys($proof['tables']), RuntimeException::class, 'Table inventory differs.'); if ($changed !== []) { file_put_contents($private.'/country-https-active-backup-renew-needed.json',json_encode([ 'at'=>gmdate('c'),'changed_tables'=>$changed,'changed_table_counts'=>array_intersect_key($tables,array_flip($changed)), 'active_SQL_writes'=>0,'action'=>'Renew snapshot/restore before staging'],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); throw new RuntimeException('Rows changed since verified snapshot; renew backup before activation.'); } $sequences=$pdo->query("SELECT * FROM pg_sequences WHERE schemaname NOT IN ('pg_catalog','information_schema') ORDER BY schemaname,sequencename")->fetchAll(PDO::FETCH_ASSOC); throw_unless($sequences === $proof['sequences'], RuntimeException::class, 'Sequence values differ.'); $counts=[]; foreach (['users','organizations','memberships','migrations','audit_events','sessions'] as $table) $counts[$table]=(int)$pdo->query('SELECT count(*) FROM "'.$table.'"')->fetchColumn(); $mfaCount=0; foreach ($pdo->query('SELECT two_factor_secret FROM users WHERE two_factor_secret IS NOT NULL')->fetchAll(PDO::FETCH_COLUMN) as $ciphertext) { $plain=$crypt->decrypt($ciphertext); throw_unless(is_string($plain) && strlen($plain)>0, RuntimeException::class, 'Original MFA envelope cannot be decrypted.'); unset($plain); $mfaCount++; } $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 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_COLUMN); throw_unless($migrations === [] && $columns === [], RuntimeException::class, 'Installed resources differ; stop instead of reinstalling.'); $pdo->exec('ROLLBACK'); $result=['result'=>'passed','at'=>gmdate('c'),'code_hash'=>$manifest['code_hash'],'delivery_revision'=>$manifest['delivery_revision'],'target'=>$identity, 'counts'=>$counts,'tables'=>$tables,'sequences_verified'=>true,'backup_verified_at'=>$proof['verified_at'],'backup_age_seconds'=>time()-strtotime($proof['verified_at']), 'backup_restore_and_actual_rows_correspond'=>true,'stable_key_match'=>true,'original_mfa_envelopes_recovered'=>$mfaCount, 'country_flag_enabled'=>false,'active_database_writes'=>0,'installed_packages'=>$migrations,'country_columns'=>$columns, 'source_code_hash'=>$proof['source_code_hash'],'readiness_proof_path'=>$read($private.'/country-https-backup-latest.json')['path']]; file_put_contents($private.'/country-https-active-preflight-20261011.json',json_encode($result,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); echo json_encode(array_diff_key($result,['tables'=>true,'readiness_proof_path'=>true]),JSON_THROW_ON_ERROR).PHP_EOL;