exec('BEGIN TRANSACTION 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); $installed = (bool) $pdo->query("SELECT EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='opportunities' AND column_name='management_version')")->fetchColumn(); $migrationApplied = (int) $pdo->query("SELECT count(*) FROM migrations WHERE migration='2026_10_09_020000_extend_opportunity_management'")->fetchColumn(); $resourceSchemaInstalled = (bool) $pdo->query("SELECT EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema='public' AND table_name='opportunity_images')")->fetchColumn(); $resourceAuditCount = (int) $pdo->query("SELECT count(*) FROM audit_events WHERE source_system IN ('opportunity-resources','opportunity-resources-install')")->fetchColumn(); $classifications = $pdo->query("SELECT DISTINCT ON (after_data->>'opportunity_id') after_data->>'opportunity_id' AS id,after_data->>'classification' AS classification FROM audit_events WHERE source_system='opportunity-origin-review' ORDER BY after_data->>'opportunity_id',occurred_at DESC,id DESC")->fetchAll(PDO::FETCH_ASSOC); $auditCount = (int) $pdo->query("SELECT count(*) FROM audit_events WHERE source_system IN ('opportunity-management','opportunity-management-install')")->fetchColumn(); $installation = $pdo->query("SELECT id,actor_user_id,occurred_at,action,after_data FROM audit_events WHERE source_system='opportunity-management-install' ORDER BY occurred_at,id")->fetchAll(PDO::FETCH_ASSOC); $backup = json_decode(file_get_contents($dir.'/opportunity-management-backup-proof.json'), true, 512, JSON_THROW_ON_ERROR); $checks = []; $restored = $backup['restored_target']; if (! str_ends_with($restored['database'], '_test') || (int) $restored['port'] !== 55441) { throw new RuntimeException('Isolated history comparison required'); } $baseline = new PDO('pgsql:host=127.0.0.1;port=55441;dbname='.$restored['database'], $c['username'], $c['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); $baseline->exec('BEGIN TRANSACTION READ ONLY'); $oldEvents = $baseline->query("SELECT id,row_to_json(t)::text AS row FROM audit_events t WHERE source_system IS DISTINCT FROM 'opportunity-management' ORDER BY row_to_json(t)::text")->fetchAll(PDO::FETCH_KEY_PAIR); if (hash('sha256', implode("\n", array_values($oldEvents))) !== $backup['table_hashes']['"public"."audit_events"']) { throw new RuntimeException('Historical baseline drift'); } $currentEvents = $pdo->query('SELECT id,row_to_json(t)::text AS row FROM audit_events t ORDER BY id')->fetchAll(PDO::FETCH_KEY_PAIR); $missing = $changed = 0; foreach ($oldEvents as $eventId => $row) { if (! isset($currentEvents[$eventId])) { $missing++; } elseif ($currentEvents[$eventId] !== $row) { $changed++; } } $baseline->exec('ROLLBACK'); $historicalAudit = ['baseline_events' => count($oldEvents), 'missing' => $missing, 'changed' => $changed, 'additional_events' => count($currentEvents) - count($oldEvents)]; foreach (['opportunities', 'opportunity_projects', 'opportunity_clusters', 'opportunity_favourites', 'interest_requests', 'interest_submission_receipts', 'investment_messages', 'tasks', 'project_locations', 'cluster_projects', 'audit_events'] as $table) { $key = '"public"."'.$table.'"'; if ($table === 'opportunities') { $columns = $pdo->query("SELECT column_name FROM information_schema.columns WHERE table_schema='public' AND table_name='opportunities' ORDER BY ordinal_position")->fetchAll(PDO::FETCH_COLUMN); $columns = array_diff($columns, ['management_version', 'opportunity_category', 'management_draft', 'management_creation_key', 'first_submitted_at', 'management_closed_once']); $from = '(SELECT '.implode(',', array_map(fn ($column) => '"'.$column.'"', $columns)).' FROM opportunities)'; } else { $from = $table === 'audit_events' ? "(SELECT * FROM audit_events WHERE source_system IS DISTINCT FROM 'opportunity-management-install')" : $key; } $rows = $pdo->query('SELECT row_to_json(t)::text FROM '.$from.' t ORDER BY row_to_json(t)::text')->fetchAll(PDO::FETCH_COLUMN); $checks[$table] = ['matches_preinstallation_backup' => hash('sha256', implode("\n", $rows)) === $backup['table_hashes'][$key], 'rows' => count($rows)]; } $pdo->exec('ROLLBACK'); $result = ['captured_at' => gmdate('c'), 'identity' => $identity, 'installed' => $installed, 'migration_applied' => $migrationApplied, 'resource_schema_installed' => $resourceSchemaInstalled, 'resource_events' => $resourceAuditCount, 'classifications' => $classifications, 'management_events' => $auditCount, 'installation_audit' => $installation, 'preservation' => $checks, 'historical_audit' => $historicalAudit, 'active_writes' => 0]; file_put_contents($dir.'/opportunity-management-active-read-only.json', json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR)); echo json_encode($result).PHP_EOL;