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

59 lines
5.3 KiB
Python

"""Verify the fixed candidate and link it from the existing audit documents."""
from pathlib import Path
import hashlib,json,zipfile,csv
from datetime import datetime,timezone
root=Path(__file__).resolve().parent.parent
private=root/'storage/app/private/investmoz-v2/portal-audit'
out=root/'outputs/investmoz-opportunity-workflow-consolidated-final-20261011'
read=lambda p:json.loads(p.read_text(encoding='utf-8-sig'))
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
m=read(out/'manifesto.json');r=read(out/'pacote.json')
assert m['revision']==r['revision'] and m['code_revision']=='f07f34a11eabc35d13d3bae88df2c10f1420f582e4600dafa88628dde6195612'
archive=out/r['archive'];assert sha(archive)==r['sha256'] and sha(out/'manifesto.json')==r['manifest_sha256']
with zipfile.ZipFile(archive)as z:
assert z.testzip() is None
for name,h in m['payload'].items():assert hashlib.sha256(z.read('payload/'+name)).hexdigest()==h
for name in ['manifesto.json','relatorio.md','procedimento.md','evidencias-por-criterio.json']:
assert z.read(name)==(out/name).read_bytes()
assert len(z.namelist())==174
old=root/'outputs/investmoz-opportunity-workflow-candidate-20261011'
assert sha(old/'investmoz-workflow-3d9d392e0a0f.zip')==m['previous_candidate']['archive_sha256']
assert sha(old/'manifesto.json')==m['previous_candidate']['manifest_sha256']
for name,h in read(private/'functional-active-files-before-20261011.json').items():assert sha(root/name)==h
b=read(private/'functional-consolidated-backup-restoration-qa-20261011.json')
assert sha(Path(b['dump_path']))==b['dump_sha256'] and sha(Path(b['files_path']))==b['files_sha256']
assert b['code_revision']==m['code_revision'] and b['build_manifest_sha256']==m['production_manifest_sha256']
assert b['acervo']['source_document']['metadata_version']==3 and len(b['acervo']['lease_documents'])==3
with zipfile.ZipFile(b['files_path'])as z:
assert z.testzip() is None
for name,h in b['file_manifest'].items():assert hashlib.sha256(z.read(name)).hexdigest()==h
csv.field_size_limit(20_000_000)
rows=list(csv.DictReader((root/'docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv').open(encoding='utf-8-sig',newline='')))
assert len(rows)==3401 and sum(int(x['Quantidade de linhas de origem']) for x in rows)==7739
text=(out/'relatorio.md').read_text(encoding='utf-8')
assert '295 tabelas, 31 sequências e 286 ficheiros' in text and '12:10:22 UTC continha 270 ficheiros' in text
assert 'Não é necessária nova recompilação' in text and '4.500 MZN / mês' in text
marker='<!-- workflow-fixed-candidate-20261011 -->'
reference=f'''{marker}
Revisão consolidada para revisão **{r['revision'][:12]}**, código **{m['code_revision'][:12]}**; C125 e arrendamento54 completo integrados. [Relatório/limitações](../../../../outputs/{out.name}/relatorio.md), [manifesto](../../../../outputs/{out.name}/manifesto.json), [procedimento e reversão](../../../../outputs/{out.name}/procedimento.md), [pacote/hashes](../../../../outputs/{out.name}/pacote.json).
Bundle anterior de produção conferido por hash, sem nova recompilação. Backup/restauro QA de **{b['at']}**: **295 tabelas,31 sequências,286 ficheiros**, incluindo acervo29/metadata3, três PDFs próprios54 e12ficheiros do delta. Não é backup do alvo ativo nem autorização de ativação. COUNTRY02 ativo/A-B/C37 preservados. A referência3d9d392e0a0f é histórica e permanece intacta.
'''
for filename in ['backlog.md','relatorio-executivo.md','workflow-criterios-saida-20261011.md']:
f=root/'docs/investmoz/v2/auditoria-portal'/filename
oldtext=f.read_text(encoding='utf-8');assert marker not in oldtext
oldtext=oldtext.replace('Candidata selada **3d9d392e0a0f**','Candidata anterior preservada **3d9d392e0a0f**').replace('Restauro QA de12:10:22UTC','Restauro QA anterior de12:10:22UTC')
f.write_text(reference+oldtext,encoding='utf-8')
staging=root/'outputs/investmoz-opportunity-workflow-consolidated-20261011'
if staging.exists():
(staging/'PREPARACAO-SUPERADA.md').write_text(f'''# Preparação documental superada
Esta preparação {read(staging/'pacote.json')['revision'][:12]} não é a revisão a disponibilizar. A revisão única final é {r['revision'][:12]}, em ../{out.name}/.
Na revisão da documentação encontrou-se uma substituição indevida da contagem histórica de270ficheiros pelo total atual286. A final distingue os dois ensaios e apresenta a composição atual. Código f07f34a11eab, bundle e backup/restauro não mudaram; não houve repetição dos percursos. Os ZIPs/manifesta anteriores foram preservados, sem autorização de ativação.
''',encoding='utf-8')
proof={'result':'passed','at':datetime.now(timezone.utc).isoformat(),'revision':r['revision'],'code_revision':m['code_revision'],'archive_sha256':r['sha256'],'manifest_sha256':r['manifest_sha256'],'payload_files':len(m['payload']),'production_assets':158,'recompilation_required':False,'previous_candidate_preserved':True,'backup_tables':295,'backup_sequences':31,'backup_files':286,'QA_acervo_metadata_version':3,'active_critical_files_preserved':True,'active_writes':0,'activation_ready':False,'activation_authorized':False,'requirements':3401,'source_occurrences':7739,'scope':'Six base demonstrated branches plus lease54; remaining category criteria explicit'}
(out/'verificacao-final.json').write_text(json.dumps(proof,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
print(json.dumps(proof,ensure_ascii=False))