Files
Investidor-V2/tools/portal-country-https-verify.py
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

117 lines
7.1 KiB
Python

"""Verify the sealed review package and the two targeted audit edits; no database access."""
from pathlib import Path
from collections import Counter
from datetime import datetime, timezone
import csv
import hashlib
import json
import zipfile
csv.field_size_limit(20_000_000)
ROOT = Path(__file__).resolve().parent.parent
PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
DOC = ROOT / 'docs/investmoz/v2/auditoria-portal'
OUT = ROOT / 'outputs/investmoz-country02-https-20261011'
read = lambda p: json.loads(Path(p).read_text(encoding='utf-8-sig'))
sha = lambda p: hashlib.sha256(Path(p).read_bytes()).hexdigest()
packet = read(PRIVATE / 'country-https-results-20261011/csv-edits.json')
csv_results = []
for edit in packet['files']:
file = DOC / edit['filename']
rows = list(csv.reader(file.open(encoding='utf-8-sig', newline='')))
assert len(rows) == len(edit['rows'])
patched = {p['row']: p['values'] for p in edit['patches']}
changed_ids = []
for i, row in enumerate(rows):
expected = list(edit['rows'][i])
for field, value in patched.get(i, {}).items():
expected[rows[0].index(field)] = value
assert row == expected, (edit['filename'], i)
if i in patched:
changed_ids.append(row[rows[0].index('ID')])
assert set(changed_ids) == {'AUD-COUNTRY-02', 'AUD-OPS-01'}
csv_results.append({'file': edit['filename'], 'changed_ids': changed_ids,
'other_cells_and_source_references_preserved': True,
'sha256': sha(file)})
requirements = list(csv.DictReader((DOC / 'matriz-requisitos.csv').open(encoding='utf-8-sig', newline='')))
assert len(requirements) == len({r['ID'] for r in requirements}) == 3393
assert sum(int(r['Quantidade de linhas de origem']) for r in requirements) == 6845
manifest = read(OUT / 'manifesto-candidata.json')
envelope = read(OUT / 'manifesto-pacote.json')
assert sha(OUT / 'manifesto-candidata.json') == envelope['manifesto_candidata_sha256']
assert sha(OUT / envelope['archive']) == envelope['archive_sha256']
with zipfile.ZipFile(OUT / envelope['archive']) as archive:
assert len(archive.namelist()) == len(set(archive.namelist())) == envelope['archive_entries'] == 200
assert set(archive.namelist()) == set(envelope['verified_members_sha256'])
for name, digest in envelope['verified_members_sha256'].items():
assert hashlib.sha256(archive.read(name)).hexdigest() == digest
assert not any(p in {'.env', 'vendor', 'node_modules', 'database.dump'} for p in Path(name).parts)
assert not name.endswith('-key.pem')
revision = hashlib.sha256(json.dumps(manifest['revision_input'], sort_keys=True, separators=(',', ':')).encode()).hexdigest()
assert revision == manifest['delivery_revision']
for name, digest in manifest['deployment_files_sha256'].items():
assert sha(OUT / name) == digest
source = Path(read(PRIVATE / 'country-https-latest.json')['source'])
for name, digest in manifest['files'].items():
assert sha(source / name) == digest
stage = read(PRIVATE / 'country-https-production-stage-latest.json')
for name, digest in stage['inputs'].items():
assert sha(source / name) == digest
for name, digest in stage['assets'].items():
assert sha(Path(stage['build_directory']) / name) == digest
for name, digest in stage['active_assets'].items():
assert sha(ROOT / 'public/build' / name) == digest
baseline = read(PRIVATE / 'country-c110-source-latest.json')
for name, digest in baseline['baseline_live_sources'].items():
assert sha(ROOT / name) == digest, name
active_config = read(OUT / 'configuracao-ativa-leitura.json')
for name in ['active_vhost', 'apache_config', 'ssl_include']:
assert sha(active_config[name]['path']) == active_config[name]['sha256']
assert sha(ROOT / 'public/build/manifest.json') == active_config['active_manifest_sha256']
for directory in ['investmoz-country02-candidate-20261011', 'investmoz-country02-c110-20261011']:
previous = ROOT / 'outputs' / directory
sealed = read(previous / 'manifesto-pacote.json')
assert sha(previous / sealed['archive']) == sealed['archive_sha256']
assert sha(previous / 'manifesto-candidata.json') == sealed['manifesto_candidata_sha256']
backup = read(read(PRIVATE / 'country-https-backup-latest.json')['path'])
assert backup['code_hash'] == manifest['code_hash']
assert sha(backup['dump_path']) == backup['dump_sha256']
assert sha(backup['files_path']) == backup['files_sha256']
for key in ['restore_verified', 'files_verified', 'sequences_verified', 'compatibility_verified', 'reversal_verified', 'qa_passed']:
assert backup[key] is True
with zipfile.ZipFile(backup['files_path']) as archive:
assert archive.read('runtime/.env') == (ROOT / '.env').read_bytes()
runtime = json.loads(archive.read('runtime/effective-runtime.json'))
assert runtime['config_cached'] == (ROOT / 'bootstrap/cache/config.php').is_file()
age = (datetime.now(timezone.utc) - datetime.fromisoformat(backup['verified_at'])).total_seconds()
assert 0 <= age <= 86400
browser = read(OUT / 'chromium-https.json')
sql = read(OUT / 'persistencia-qa.json')
quality = read(OUT / 'validacao-qa.json')
assert browser['result'] == sql['result'] == 'passed'
assert browser['code_hash'] == sql['code_hash'] == manifest['code_hash']
assert all(value is True if isinstance(value, bool) else value['encrypted'] and not value['plainHistory'] and not value['privateKeysPresent'] for value in browser['checks'].values())
assert browser['javascript_errors'] == browser['mixed_requests'] == []
assert quality['phpunit_result'] == quality['phpstan_result'] == quality['production_build'] == 'passed'
assert sql['tables'] == 288 and sql['new_tables'] == 0 and sql['other_packages_installed'] is False
runtime_final = read(PRIVATE / 'country-https-final-runtime.json')
assert runtime_final['qa_ca_trusted'] is True and runtime_final['active_ca_trusted'] is False
assert runtime_final['temporary_qa_listener_ports'] == []
assert manifest['ready_for_review'] is True and manifest['active_activation_performed'] is False
assert manifest['active_configuration_changed'] is False and manifest['active_writes'] == 0
summary = {'result': 'passed', 'at': datetime.now(timezone.utc).isoformat(),
'requirements': 3393, 'source_occurrences': 6845,
'states': dict(Counter(r['Estado'] for r in requirements)), 'csv_preservation': csv_results,
'active_sources_assets_environment_apache_and_previous_packages_unchanged': True,
'package_members_verified': 200, 'production_assets_verified': len(stage['assets']),
'code_hash': manifest['code_hash'], 'delivery_revision': revision,
'package_sha256': envelope['archive_sha256'], 'backup_verified_at': backup['verified_at'],
'backup_age_minutes': round(age / 60, 1), 'C110_C111_C112': 'QA demonstrated',
'AB_C37_scope_preserved': True, 'temporary_qa_servers_stopped': True,
'active_tls_not_installed_or_trusted': True, 'active_writes': 0,
'activation_requires_reviewed_replacement_revision_and_HTTPS_authorization': True}
(OUT / 'verificacao-final.json').write_text(json.dumps(summary, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps(summary, ensure_ascii=False))