getMessage().PHP_EOL); exit(1); }); $app = require $root.'/bootstrap/app.php'; (new LoadEnvironmentVariables)->bootstrap($app); (new LoadConfiguration)->bootstrap($app); $read = static fn (string $path): array => json_decode(file_get_contents($path), true, 512, JSON_THROW_ON_ERROR); $dir = $root.'/storage/app/private/investmoz-v2/portal-audit'; $proof = $read($read($dir.'/country-candidate-backup-latest.json')['path']); $manifest = $read($root.'/outputs/investmoz-country02-candidate-20261011/manifesto-candidata.json'); $installer = new OrganizationCountryInstallation; throw_unless($installer->fingerprint() === '36f7722ce5a51abc6a246116afcab22ebc8167fa3d06e493920ad18c7afbfca8' && $manifest['delivery_revision'] === 'c68ceef9d4a3bc10da7bf269c1261a7b1edece3c1e114d6fef8cc60ca9f4403c', RuntimeException::class, 'Approved code/delivery differs.'); $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.'); $pdo = new PDO('pgsql:host='.$c['host'].';port='.$c['port'].';dbname='.$c['database'], $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, 'Server target differs.'); $evidence = $installer->evidence((object) ['database' => $identity['database'], 'port' => (int) $identity['port']]); throw_unless($evidence['ready'], RuntimeException::class, 'Backup/readiness invalid or expired.'); $installations = $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($installations === $proof['source_installations']['migrations'] && $columns === $proof['source_installations']['country_columns'], RuntimeException::class, 'Schema/ledger diverges from reviewed pre-installation state.'); $runtime = ['config_cached' => $app->configurationIsCached(), 'cipher' => config('app.cipher'), 'session_driver' => config('session.driver'), 'app_name' => config('app.name'), 'organization_country_enabled' => (bool) config('portal.organization_country_enabled'), 'opportunity_dashboard_access_enabled' => (bool) config('portal.opportunity_dashboard_access_enabled'), 'profile_access_enabled' => (bool) config('portal.profile_access_enabled'), 'opportunity_specialized_drafts_enabled' => (bool) config('portal.opportunity_specialized_drafts_enabled'), 'opportunity_modular_profiles_qa_enabled' => (bool) config('portal.opportunity_modular_profiles_qa_enabled'), 'legacy_content_qa_enabled' => (bool) config('portal.legacy_content_qa_enabled'), 'investor_path_enabled' => (bool) config('investor-path.enabled')]; throw_unless($runtime === $proof['runtime'], RuntimeException::class, 'Runtime flags/configuration differs from reviewed state.'); $tables = []; 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))]; } $different = []; foreach ($tables as $name => $v) { if (($proof['tables'][$name] ?? null) !== $v) { $different[] = $name; } } throw_unless(array_keys($tables) === array_keys($proof['tables']), RuntimeException::class, 'Table inventory changed.'); $counts = []; foreach (['users','organizations','memberships','migrations','audit_events','sessions'] as $table) { $counts[$table] = (int) $pdo->query('SELECT count(*) FROM "'.$table.'"')->fetchColumn(); } $pdo->exec('ROLLBACK'); $archive = new ZipArchive; throw_unless($archive->open($proof['files_path']) === true, RuntimeException::class, 'Backup runtime archive unreadable.'); $archivedRuntime = json_decode($archive->getFromName('runtime/effective-runtime.json'), true); if (! is_array($archivedRuntime)) { // Archive entry names are private and are not echoed. for ($i = 0; $i < $archive->numFiles; $i++) { $entry = $archive->getNameIndex($i); if (str_ends_with($entry, 'effective-runtime.json')) { $archivedRuntime = json_decode($archive->getFromIndex($i), true); break; } } } $archive->close(); throw_unless(is_array($archivedRuntime) && ($archivedRuntime['app_key'] ?? $archivedRuntime['key'] ?? null) === config('app.key'), RuntimeException::class, 'Stable runtime key cannot be verified against archive.'); $result = ['result' => $different === [] ? 'passed' : 'renew_backup_before_activation', 'at' => gmdate('c'), 'authorization' => ['scope' => 'COUNTRY02 only, 050000 only', 'delivery_revision' => $manifest['delivery_revision'], 'code_hash' => $installer->fingerprint()], 'target' => $identity, 'origin' => config('app.url'), 'runtime' => $runtime, 'evidence' => $evidence, 'backup_age_seconds' => time() - strtotime($proof['verified_at']), 'backup_code_build_match' => $proof['code_hash'] === $installer->fingerprint() && $proof['production_manifest_sha256'] === $manifest['production']['manifest_sha256'], 'stable_key_match' => true, 'counts' => $counts, 'tables' => $tables, 'changed_since_snapshot' => $different, 'installations' => $installations, 'country_columns' => $columns, 'active_database_writes' => 0]; file_put_contents($dir.'/country-activation-preflight-20261011.json', json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR)); echo json_encode(array_diff_key($result, ['tables' => true]), JSON_THROW_ON_ERROR).PHP_EOL;