Files
Investidor-V2/tools/investmoz-v2-opportunity-association-qa.php
T

43 lines
3.0 KiB
PHP

<?php
// Read-only verification in the restored QA database; never connect to the active target.
$directory = dirname(__DIR__).'/storage/app/private/investmoz-v2';
$proof = json_decode(file_get_contents($directory.'/territory-backup-proof.json'), true, 512, JSON_THROW_ON_ERROR);
$plan = json_decode(file_get_contents($directory.'/opportunity-association-plan.json'), true, 512, JSON_THROW_ON_ERROR);
$target = $proof['restored_target'];
if (! $proof['restore_verified'] || ! preg_match('/^desk_restore_\d{8}_\d{6}_test$/', $target['database']) || (int) $target['port'] !== 55441) {
throw new RuntimeException('Isolated restored QA required.');
}
$pdo = new PDO('pgsql:host=127.0.0.1;port=55441;dbname='.$target['database'], 'postgres', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$pdo->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);
if ($identity['database'] !== $target['database'] || (int) $identity['port'] !== 55441 || $identity['read_only'] !== 'on' || $plan['associations'] !== [] || $plan['deletions'] !== []) {
throw new RuntimeException('QA identity or review-only plan mismatch.');
}
$checks = [];
foreach ($plan['records'] as $record) {
$statement = $pdo->prepare('SELECT reference,title,description FROM opportunities WHERE id=?');
$statement->execute([$record['id']]);
$current = $statement->fetch(PDO::FETCH_ASSOC);
if (! $current || $current['reference'] !== $record['reference'] || $current['title'] !== $record['title'] || $current['description'] !== $record['description']) {
throw new RuntimeException('QA record identity differs.');
}
foreach (['opportunity_projects' => 'project_id', 'opportunity_clusters' => 'cluster_id'] as $table => $column) {
$statement = $pdo->prepare('SELECT '.$column.' FROM '.$table.' WHERE opportunity_id=? ORDER BY '.$column);
$statement->execute([$record['id']]);
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
$expected = $table === 'opportunity_projects' ? $record['existing_projects'] : $record['existing_clusters'];
if ($rows !== $expected) {
throw new RuntimeException('Existing relationships differ.');
}
}
if ($record['unequivocal_links'] !== [] || array_filter($record['options'], fn ($option) => $option['relation_proven'])) {
throw new RuntimeException('An option was promoted without a decision.');
}
$checks[] = ['id' => $record['id'], 'identity_matches' => true, 'existing_links_preserved' => true, 'no_option_applied' => true];
}
$pdo->exec('ROLLBACK');
$evidence = ['recorded_at' => gmdate('c'), 'identity' => $identity, 'checks' => $checks, 'plan_has_no_writes' => true, 'active_writes' => 0];
file_put_contents($directory.'/opportunity-association-qa.json', json_encode($evidence, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
echo json_encode($evidence, JSON_THROW_ON_ERROR).PHP_EOL;