Files
Investidor-V2/tools/portal-visual-results-verify.py
nala 20971d523f
tests / ci (push) Canceled after 0s
oportunidades 6
2026-10-10 21:17:46 +02:00

58 lines
3.8 KiB
Python

"""Read-only preservation checks and a private technical snapshot, not an accepted candidate."""
import csv
import hashlib
import json
from datetime import datetime, timezone
from pathlib import Path
csv.field_size_limit(16000000)
root = Path(__file__).resolve().parent.parent
private = root / 'storage/app/private/investmoz-v2/portal-audit'
docs = root / 'docs/investmoz/v2/auditoria-portal'
packet = json.loads((private / 'visual-finalize-20261010/csv-edits.json').read_text(encoding='utf-8'))
checks = {}
for edit in packet['files']:
actual = list(csv.reader((docs / edit['filename']).open(encoding='utf-8-sig', newline='')))
original = edit['rows']
assert len(actual) == len(original)
header = original[0]
allowed = set(edit['allowed_columns']) | ({'SHA256', 'Bytes'} if edit['filename'] == 'inventario-fontes.csv' else set())
assert all(left == right for a, b in zip(actual, original) for key, left, right in zip(header, a, b) if key not in allowed)
checks[edit['filename']] = {'rows': len(actual)-1, 'unmodified_columns_preserved': True}
if edit['filename'] == 'matriz-requisitos.csv':
assert len({row[0] for row in actual[1:]}) == 3393
assert sum(int(row[header.index('Quantidade de linhas de origem')]) for row in actual[1:]) == 6845
for row in actual[1:]:
json.loads(row[header.index('Critérios e versões por origem (JSON)')])
if edit['filename'] == 'inventario-fontes.csv':
for entry in edit['source_hash_updates']:
row = actual[entry['row']]
path = Path(row[header.index('Exemplar/caminho')])
assert hashlib.sha256(path.read_bytes()).hexdigest() == row[header.index('SHA256')]
qa = json.loads((private / 'profile-installation-backup-qa.json').read_text(encoding='utf-8'))
active = json.loads((root / 'storage/app/private/virtual-desk/backup-proof.json').read_text(encoding='utf-8'))
status = json.loads((private / 'profile-installation-status-qa.json').read_text(encoding='utf-8'))
assert active['target'] == {'database': 'investemoz', 'port': 5432}
assert active['restored_target']['port'] == 55441 and active['restored_target']['database'].endswith('_test')
assert qa['code_hash'] == status['code_hash']
manifest = {}
for name in ['app', 'config', 'database', 'resources', 'routes', 'tests', 'tools']:
for file in (root / name).rglob('*'):
if file.is_file() and file.suffix in ['.php', '.py', '.mjs', '.cjs', '.js', '.ts', '.tsx'] and not {'__pycache__', 'node_modules'}.intersection(file.parts):
manifest[file.relative_to(root).as_posix()] = hashlib.sha256(file.read_bytes()).hexdigest()
manifest['bootstrap/app.php'] = hashlib.sha256((root / 'bootstrap/app.php').read_bytes()).hexdigest()
active_hash = hashlib.sha256((root / 'public/build/manifest.json').read_bytes()).hexdigest()
assert active_hash == '75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94'
proof = {'captured_at': datetime.now(timezone.utc).isoformat(),
'scope': 'Technical QA snapshot only; global activation candidate not fixed',
'code_hashes': manifest,
'qa_build_manifest_sha256': hashlib.sha256((root / 'public/build-qa-opportunities/manifest.json').read_bytes()).hexdigest(),
'active_build_manifest_sha256': active_hash, 'active_build_unchanged': True,
'installation_fingerprint': qa['code_hash'], 'qa_restore': qa['restored_target'],
'qa_backup_at': qa['verified_at'], 'active_readonly_restore': active['restored_target'],
'active_backup_at': active['verified_at'], 'active_restore_candidate_migrations_tested': False,
'active_writes': 0, 'matrix': checks}
(private / 'visual-finalize-20261010/technical-snapshot.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps({'verified': checks, 'active_build_unchanged': True, 'global_candidate_fixed': False, 'active_writes': 0}))