58 lines
3.8 KiB
Python
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}))
|