139 lines
23 KiB
Python
139 lines
23 KiB
Python
"""Seal one bounded QA candidate, with destination blockers distinct from clone evidence."""
|
||
from pathlib import Path
|
||
from datetime import datetime,timezone
|
||
import json,hashlib,zipfile,shutil,csv,collections,xml.etree.ElementTree as ET
|
||
csv.field_size_limit(20000000)
|
||
R=Path(__file__).resolve().parent.parent;P=R/'storage/app/private/investmoz-v2/portal-audit';D=R/'docs/investmoz/v2/auditoria-portal'
|
||
read=lambda n:json.loads((P/n).read_text(encoding='utf-8'))
|
||
sha=lambda p:hashlib.sha256(Path(p).read_bytes()).hexdigest()
|
||
code=read('workflow-upgrade-code-20261011.json');build=read('workflow-upgrade-production-build-20261011.json');backup=read('workflow-upgrade-backup-restoration-qa-20261011.json');target=read('workflow-upgrade-target-backup-20261011.json')
|
||
deps=read('workflow-upgrade-final-previews-chromium-20261011.json');counts=read('workflow-upgrade-finalize-20261011/counts.json');source=Path(read('workflow-upgrade-latest.json')['source'])
|
||
oldFolder=R/'outputs/investmoz-opportunity-workflow-scope-20261011';old=json.loads((oldFolder/'manifesto.json').read_text(encoding='utf-8'));oldPackage=json.loads((oldFolder/'pacote.json').read_text(encoding='utf-8'))
|
||
oldZip=next(oldFolder.glob('*.zip'));assert sha(oldZip)==oldPackage['sha256']
|
||
for p in [backup,target]:
|
||
assert p['result']=='passed'
|
||
for field in ['dump_path','files_path']:assert sha(p[field])==p[field.replace('_path','_sha256')]
|
||
assert code['code_revision']==backup['code_revision']==target['candidate_code_revision']
|
||
assert build['manifest_sha256']==code['production_manifest_sha256']==backup['production_manifest_sha256']==target['candidate_qa_manifest_sha256']
|
||
assert deps['result']=='passed' and deps['resources_preview']['code_hash']==backup['resource_fingerprint'] and deps['profiles_preview']['code_hash']==backup['profile_fingerprint']
|
||
names=['workflow-upgrade-fixed-install-chromium-20261011.json','workflow-upgrade-document-pipeline-chromium-20261011.json','workflow-upgrade-office-chromium-20261011.json','workflow-upgrade-final-ui-chromium-20261011.json','workflow-upgrade-final-previews-chromium-20261011.json']
|
||
for n in names:assert read(n)['result']=='passed'
|
||
for n,h in code['code_files'].items():assert sha(source/n)==h
|
||
assert len(code['code_files'])==17 and len(build['assets'])==158
|
||
for n,h in code['active_base_hashes'].items():assert (sha(R/n)if(R/n).is_file()else None)==h
|
||
for n,h in read('functional-active-files-before-20261011.json').items():assert sha(R/n)==h
|
||
blocked=[
|
||
{'id':'B1','condition':'Atualizar/validar o ClamD real do destino e a atualização periódica das definições','evidence':'Leitura15:05Z:ClamD3310 versão1.5.4,assinaturas09out08:25Z,signatures_stale;QA13310assinaturas11out08:26Z.','success':'Health disponível dentro do limite48h e scan real de um ficheiro autorizado no destino;sem herdarem clean daQA.'},
|
||
{'id':'B2','condition':'Configurar/verificar worker supervisionado e runtime documental efetivo no destino','evidence':'Destino tem QUEUE_CONNECTION=database; isso não comprova worker. Snapshot com0jobs/0failed_jobs. Clone demonstra worker,210s,repetição,GD/WebP e recuperar bytes.','success':'PHP/extensões/limites/serviço real e reinício controlado verificados;worker processa envio autorizado e scans das derivadas,sem acesso indevido. Sem ingerir dados sintéticosQA.'},
|
||
{'id':'B3','condition':'Designar titulares legítimos, aprovador independente e âmbitos funcionais','evidence':'No destino há2gestores verificados comMFA;bootstrap exige3pessoas distintas. Zero organizações/representações. Só contas sintéticas foram preparadas nosclones.','success':'Responsável identifica2titulares+terceiro gestorMFA e perfis/tipos/organizações legítimos;cerimónia e concessões autenticadas. Não é necessário inventar organização para instalar.'}]
|
||
payload={**code['code_files'],**{'public/build/'+n:h for n,h in build['assets'].items()}}
|
||
core={k:v for k,v in old.items()if k not in ['revision','sealed_at']}
|
||
core.update({'format':'investmoz-workflow-upgrade-candidate-v1','previous_candidate':old['revision'],'code_revision':code['code_revision'],'payload':payload,'base_hashes':{n:sha(R/n)if(R/n).is_file()else None for n in payload},
|
||
'additional_changes':{'changed_from_previous':code['changed_from_previous'],'superuser':'Perfil operacional no âmbito + elevação independente de consulta,registo15min/MFA;sem acesso administrativo universal.','images':'Derivadas reutilizadas porhash/original;repetição sem novosstreams/versões/decisões.','UI':'Privacidade explícita e ação de consulta identificada.','after_installer_rehearsal':code['changed_since_authenticated_installer'],'after_installer_effect':code['installer_delta_scope']},
|
||
'production_manifest_sha256':build['manifest_sha256'],'recompilation_required':True,'profile_fingerprint':backup['profile_fingerprint'],'resources_fingerprint':backup['resource_fingerprint'],
|
||
'effects':{'code_files':17,'build_assets':158,'configuration':'Só flags do workflow após autorização/designações;preservarCOUNTRY02,HTTPS,cookie e chaves. Nenhuma configuração ativa alterada neste ensaio.','services':'ClamD e worker do destino ainda necessários;não demonstrados por configurarQA.','schema':'030000:3tabelas+documents.storage_encryption;040000:4tabelas+users.portal_access_revision+3colunasemopportunities. Total7tabelas/5colunas;020000jáexiste;050000preservada;190000fora.','data':'Não importaQA,cria contas,organizações,representações ou converte donos/estados históricos. Instalações acrescentam ledger/auditoria;bootstrap/grants são atos separados.'},
|
||
'privacy_policy':'Anexos privados seguem autorização vigente da oportunidade,tipo/organização e estado. Superuseradministrativo isolado não consulta;precisa de âmbito e elevação independente deconsulta para o registo. Auditor autorizado conserva leitura e restrição operacional. Classificação/publicação de anúncio não concede acesso ao ficheiro. Partilha individual permanece indisponível.',
|
||
'QA_evidence':{n:sha(P/n)for n in names},'reused_evidence':{'candidate':old['revision'],'criteria':old['reused_evidence'],'closures':['A/B','C37'],'not_repeated':'Coedição,contratos/workflowdas seis categorias e demais critérios válidos;repetidos apenas instalação/processamento/ACL/UIafetados.'},
|
||
'quality':{'production_build':True,'typescript_no_emit_exit':0,'affected_tests':'3testesafetados passaram no primeiro lote;teste novo corrigido após contrariar a própria constraint de autoaprovação,passou29assertions. Erro do roteiro/teste preservado;não foi falha do portal.','policy_validity_xml_sha256':sha(Path(read('portal-stability-latest.json')['source'])/'storage/workflow-upgrade-policy-validity-20261011.xml'),'image_and_previous_permissions_xml_sha256':sha(Path(read('portal-stability-latest.json')['source'])/'storage/workflow-upgrade-affected-20261011.xml')},
|
||
'QA_backup':{k:backup[k]for k in ['verified_at','target','restored','dump_sha256','files_sha256','table_count','sequence_count','file_count','MFA_envelopes_readable','original_non_transient_tables_preserved']},
|
||
'destination_backup':{k:target[k]for k in ['verified_at','target','restored_target','dump_sha256','files_sha256','file_count','MFA_envelopes_readable','active_originals_backed_up']},
|
||
'COUNTRY02_compatibility':{'active_ON':True,'050000_not_reapplied':True,'original_rows_cipher_history_preserved':True,'organizations_still_zero':'No real master-country write demonstration without legitimate organization/representation;not an installer block.'},
|
||
'destination_inventory':read('workflow-upgrade-target-readonly-20261011.json'),'destination_services_read_only':read('workflow-upgrade-destination-services-readonly-20261011.json'),
|
||
'activation_ready':False,'activation_authorized':False,'activation_blocks':blocked,'new_acervo_import_or_publication_included':False,'QA_fixtures_in_delivery':False,'audit_counts':counts})
|
||
revision=hashlib.sha256(json.dumps(core,sort_keys=True,separators=(',',':'),ensure_ascii=False).encode()).hexdigest();manifest={**core,'revision':revision,'sealed_at':datetime.now(timezone.utc).isoformat()}
|
||
out=R/'outputs/investmoz-workflow-upgrade-20261011';assert not(out/'manifesto.json').exists(),'Previous fixed candidate must not be overwritten';out.mkdir(exist_ok=True)
|
||
(out/'manifesto.json').write_text(json.dumps(manifest,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
|
||
report=f'''# Ensaio de atualização e candidata {revision[:12]}
|
||
|
||
**Código preparado e critérios abaixo demonstrados em QA; não pronta para disponibilização ativa.** Código `{code['code_revision']}`. A candidata `e871f8aadb59` fica preservada como referência. COUNTRY02 ativo e fechos A/B/C37 não foram alterados nem repetidos. Sem escrita no destino.
|
||
|
||
## Provas do clone e verificações do destino
|
||
|
||
| Critério | Demonstração do clone | Destino, somente leitura |
|
||
| --- | --- | --- |
|
||
| 030000→040000 | Chromium HTTPS/MFA normal; prévia divergente409 semDDL; repetição030000 exige renovar prévia,sem duplicação;040000 mantém chave/mesmo recibo e rejeita conteúdo divergente. Instalação não concede perfis. Bootstrap distinto com duas contas sintéticas e terceiro aprovador. | 020000/050000 instaladas;030000/040000 ausentes;COUNTRY02ON,demaisflagsOFF. |
|
||
| Preservação | Snapshot288tabelas; adição prevista7→295. Up/down/rollback vazio conferido. Após uso,285tabelas originais não transitórias preservadas pelos campos originais; originais,permissões,histórico e doisMFA antigos conservados. Zero organizações/representações em todosestesclones. | 288tabelas,13contas,0organizações/representações/geometrias;nenhuma alteração ativa. |
|
||
| Envio/fila/scan | PDF e PNG enviados pelo navegador ao servidorQA. Quarentena423. Falha **injetada e identificada**:worker sai70 após reservar umjob;original/fila preservados. Mesmojob retoma após o prazo real210s,sem reenvio. | Configuração database e0jobs/0failed_jobs no snapshot não comprovam worker supervisionado. |
|
||
| ClamD/derivadas | ClamD1.5.4/13310,assinaturas11out08:26UTC;GD/WebP real. TrêsWebP320/640/800 com scans independentes. Repetição200 mantémUUIDs,hashes,cifra,versões e decisões. Originais cifrados preservados;recuperação exata porhash. | ClamD3310,assinaturas09out08:25UTC,stale/indisponível. Não foi atualizado neste âmbitoQA. |
|
||
| Tipos/documentos | PDF/PNG/3WebP eDOCX/XLSX recuperáveis; Office não é convertido/publicado automaticamente. Provas anteriores de contratos/documentos das seis categorias conservadas. | Nenhum ficheiroQA importado ou publicado. Outros consumidores/exportações normativas não encerrados por estes testes. |
|
||
| Superutilizador | Sem âmbito403;com âmbito ainda403 sem elevação. Outro titular aprova consulta para umdossier15min:200/hash;autoaprovação/outro dossier403. Revogação invalida sessão/URL anterior e novo login403. Expiração e Auditor acumulado recusados no teste afetado. | Não há titulares novos escolhidos ou privilégios alterados. |
|
||
| Interface/bundle | Aviso de privacidade e derivada visíveis390px;opção «Consultar dossier e anexos»;hash doJS servido confere com compilação final. Roteiros inicialmente pararam por erros de rota/parser/seleção da aba;corrigidos,separados de falhas do portal. | Bundle/HTTPS/cookie/chaves ativos inalterados. |
|
||
|
||
Atualização final do rótulo de consulta alterou apenas`resources/js/pages/profiles/administration.tsx` após o ensaio de instalação;pedidos,autorização,DDL,transações e política iguais. A interface/bundle afetados foram reensaiados e as prévias/backup foram renovados para os fingerprints finais. Não se apresenta o fingerprint anterior como o final.
|
||
|
||
## Âmbito incluído e indisponível
|
||
|
||
Mantém as seis categorias base e as variantes delimitadas da candidata anterior:projeto;venda/arrendamento imobiliário concluído,desocupado,sem encargos;fundiário;venda de negócio;parceria;franquia. Provas30–35/54,renda4500MZN/mês,materialidade/revisões independentes e coedição são reutilizadas. Este lote reforça instalação,anexos e processamento;não certifica toda variante ou decisão externa.
|
||
|
||
**Indisponíveis:** restauração de oportunidade;ACL/partilha por destinatário individual;Response/§27normativo integral;variantes não ensaiadas;módulos/ofertas/SLA;legado;percurso integrado190000;importação/divulgação de camadas;dispositivos físicos/acessibilidade integral. Os limites permanecem visíveis e as flags própriasOFF. Cartografia do destino tem1990registos e zero geometrias: cadastro não comprova mapas com limites. Não instalar/importar camadas para contornar isso neste pacote.
|
||
|
||
R-ARCHIVE continua proposta separada:Publicador autorizado/independente comMFA,motivo/auditoria→`needs_information` não público,nunca republicação automática. R-DRAFT tem regra própria:autor/coeditorPromotor autorizado→`draft` privado,só se nunca submetido/publicado. Restauro de anexos anterior é distinto. Nenhuma proposta foi ativada.
|
||
|
||
## Lista única de bloqueios restantes à disponibilização
|
||
|
||
1. **B1 — ClamD do destino:** atualizar definições oficiais,validarhealth/scan real e periodicidade. Prova do13310QA não é prova do3310ativo.
|
||
2. **B2 — execução documental do destino:** worker supervisionado,PHP/extensões/GD/WebP/limites e recuperação real;configuração de fila isoladamente não basta. Rever fila antes de iniciar;atualmente0jobs/0falhas no snapshot.
|
||
3. **B3 — designações legítimas:** dois titulares,terceiro gestor independente comemail/MFAconfirmados e perfis/âmbitos funcionais. Hoje só2gestoresMFA são elegíveis;ninguém foi escolhido. Organizações podem ser preenchidas posteriormente pelo fluxo legítimo;instalar não exige criar uma organização fictícia.
|
||
|
||
Depois destas condições,a revisão completa continua a precisar de autorização própria antes de disponibilização. Restauração/partilha e demais exclusões são decisões/frentes separadas,sem bloquear artificialmente o workflow delimitado.
|
||
|
||
## Designações concretas a fornecer pelo responsável
|
||
|
||
- TitularA e TitularB:duas contas legítimas distintas,verificadas eMFAconfirmado.
|
||
- Gestor da cerimónia:terceira conta distinta,legitimamente autorizada para instalação,verificada eMFAconfirmado;aprova o bootstrap.
|
||
- Promotores:identidade legítima,individual ou representação real existente,tipo autorizado;pedido documental e decisão independente.
|
||
- Validador e Publicador:contas/âmbitos/tipos concretos,independentes do autor/editor/representante e entre aprovação/publicação. Coordenador/revisores/recurso só para responsabilidades efetivamente designadas;nenhum nome,SLA ou suplência inventado.
|
||
|
||
## Backup/restauro correspondente
|
||
|
||
Destino READONLY `{target['target']['database']}:{target['target']['port']}`,verificado`{target['verified_at']}`:288tabelas/31seq/799ficheiros/4originaisprivados/2MFA,restauro exclusivoQA. Inclui configuração/chaves/certificado/vhosts/bundle ativos em arquivo privado,**não na entrega**. Pós-usoQA`{backup['verified_at']}`:295tabelas/31seq/188ficheiros/9MFA. Diferença288→295 são exatamente7tabelas030000+040000. BackupQA nunca substitui o snapshot do alvo. Renovar/revalidar após atualização de serviços,alteração do alvo/revisão,expiração ou antes da intervenção futura.
|
||
|
||
## Matriz e evidências
|
||
|
||
Mesma matriz:{counts['requirements']}requisitos/{counts['rows']}linhas,{counts['source_occurrences']}ocorrências. Só seteIDs atualizados,zero novos requisitos. Estados preservados:{counts['states']}. C127 identifica leitura administrativa global encontrada por código;C128 identifica geração repetida incondicional. As provasHTTP posteriores são explicitamente distinguíveis das constatações de código.
|
||
|
||
Ver`evidencias-por-criterio.json`,`manifesto.json`e`procedimento.md`. Testes/hashes sustentam os resultados visíveis e recuperáveis;não substituem a verificação do destino. Nenhuma ativação incluída.
|
||
'''
|
||
(out/'relatorio.md').write_text(report,encoding='utf-8')
|
||
procedure=f'''# Procedimento único — candidata {revision[:12]}; ativação ainda não autorizada
|
||
|
||
1. Conferir pacoteSHA-256/manifesto/revisão`{revision}`/código`{code['code_revision']}`e baseline485ee04c40b2. Resolver B1–B3 antes de disponibilizar. Preservar a referência anterior;nenhuma migração global/seed/importação.
|
||
2. Agrupar intervenções necessárias:responsável designa2titulares+terceiro gestor+âmbitos;operador configura scanner/atualizador eworker supervisionado,certifica PHP/extensões/GD/WebP. Qualquer atualização destes serviços do ativo e disponibilização desta revisão requer autorização própria. Não pedir ao investidor para descobrir a infraestrutura incompleta.
|
||
3. Revalidar alvo READONLY,COUNTRY02ON/050000,ledger/schema020000/030000/040000 eprivilegios. Renovar backup/restauro físico do alvo/chaves/originais/TLS/vhosts e conferir hashes desta revisão após os ajustes. Hoje:288tabelas,030/040ausentes,13contas/0org/0representações,0jobs;parar se houver divergência. Após uso,não executar down/drop/restauro completo automático.
|
||
4. Sob futura autorização:disponibilizar17ficheiros+158assets com workflowOFF. ManterCOUNTRY02ON,HTTPS,cookie,chaves,histórico. Este delta não substituiDLL nem configuraHTTPS. Se umserviço precisar de reinício,usar controlo normal doLaragon/conferirvhosts;não terminar processos indiscriminadamente. Verificarhashes doasset efetivamente servido.
|
||
5. Gestor existente com email verificado faz login/MFA normalmente. GET`https://portal-investidor.test/management/opportunity-resources-install`:prévia alvo/fingerprint`{backup['resource_fingerprint']}`/backup/installed/ready esperados. POST na mesma rota **com`hash,confirm`**;030000 não utiliza o reciboUUID de040000. Aplicar somente030000 se ausente;prévia antiga409 exigeGETnovo. Se já instalada,recuperar prévia atual e não reinstalar;a repetição com prévia atual não duplica ledger/auditoria. Parar antes de aplicar em divergência/readinessausente.
|
||
6. GET`https://portal-investidor.test/management/profile-install`:030000 íntegra,020000 e identidade/auditoria existentes;190000 não é dependência. Conferir fingerprint`{backup['profile_fingerprint']}`,target/hash/schema/backup. POST **`hash,confirm,idempotency_key,reason`**,UUID criptográfico estável para a mesma tentativa;mesma chave/conteúdo devolve o mesmo recibo,conteúdo divergente409. Aplicar somente040000. Zero contas/grants/organizações/representações automáticos;050000 não reaplicada.
|
||
7. Bootstrap separado POST`/management/profile-install/bootstrap`,prévia atual,`hash,confirm,idempotency_key,first_user_id,second_user_id,reason`;terceiro gestor distinto comMFA recente. Só titulares legitimamente designados,exatamente2. Atribuições pelo pedido documental/perfis existentes,sem autoconcessão. Instalar é independente de preencher posteriormente cadastros legítimos.
|
||
8. Habilitar só`PORTAL_PROFILE_ACCESS_ENABLED`,`PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED`,`PORTAL_OPPORTUNITY_SPECIALIZED_DRAFTS_ENABLED`no âmbito futuro autorizado. COUNTRY02 continuaON. Modulares,legado,190000,ofertas/SLA,restauração/partilha individual continuam indisponíveis. Publicação de oportunidade exige ação própria,não decorre da instalação.
|
||
9. Critérios de sucesso no destino:030/040ledger/schema coerentes e uma auditoria por instalação;050/Country eoriginais/histórico intactos;loginMFA/sessão;perfil legítimo→rascunho→guardar/recuperar→envio/quarentena→worker/scan/derivadas→hash/preview autorizado. Super sem âmbito/elevação,autoaprovação,fora do dossier e grant revogado recusados nas rotas próprias/genéricas/assinadas. Conferirbundle e resultado visível. ReutilizarA/B,C37 e provas anteriores;não repetir sem alteração relevante. Gravação real de país mestre permanece pendente até existir organização legítima representada;isso não impede instalar030/040.
|
||
10. Contenção:desligar somente flags do workflow e parar novos processamentos desse âmbito pelo controlo do serviço,preservando scanner seguro. **Conservar C126/C127 e a correção comum dos binários**;não repor leitura universal. PreservarHTTPS,cookie,COUNTRY02,colunas,originais/cifra,histórico,auditoria. DDL falhado deve reverter transação/ledger. Após utilização,nenhum down/drop;restauro completo ou recuperação destrutiva exige decisão separada e reconciliação das escritas posteriores. Restauração de oportunidades nunca repõe publicação automaticamente.
|
||
'''
|
||
(out/'procedimento.md').write_text(procedure,encoding='utf-8')
|
||
evidence={n:read(n)for n in names};evidence['worker_fault']=read('workflow-upgrade-worker-fault-20261011.json');evidence['reused_previous_criteria']=old['reused_evidence'];evidence['scope_note']='Clones55441;no active mutation;failure deliberately injected. Credentials/cookies/MFA codes and signed query omitted.'
|
||
(out/'evidencias-por-criterio.json').write_text(json.dumps(evidence,ensure_ascii=False,indent=2),encoding='utf-8')
|
||
zipPath=out/('investmoz-workflow-'+revision[:12]+'.zip')
|
||
with zipfile.ZipFile(zipPath,'w',zipfile.ZIP_DEFLATED)as z:
|
||
for n,h in payload.items():assert sha(source/n)==h;z.write(source/n,n)
|
||
for n in ['manifesto.json','relatorio.md','procedimento.md','evidencias-por-criterio.json']:z.write(out/n,'review/'+n)
|
||
with zipfile.ZipFile(zipPath)as z:
|
||
for n,h in payload.items():assert hashlib.sha256(z.read(n)).hexdigest()==h
|
||
assert not any(n.startswith(('storage/','vendor/','node_modules/')) or n.endswith(('.env','.dump'))for n in z.namelist())
|
||
package={'revision':revision,'code_revision':code['code_revision'],'filename':zipPath.name,'sha256':sha(zipPath),'manifest_sha256':sha(out/'manifesto.json'),'payload_files':len(payload),'code_files':17,'build_assets':158,'activation_ready':False,'activation_authorized':False,'active_writes':0}
|
||
(out/'pacote.json').write_text(json.dumps(package,indent=2),encoding='utf-8')
|
||
marker='workflow-upgrade-qa-20261011'
|
||
brief=f'''\n<!-- {marker} -->
|
||
## Atualização do clone do destino — {revision[:12]}
|
||
|
||
**QA demonstrada; ativo não atualizado.**030000→040000 autenticadas no clone real288→295;050000/COUNTRY02,originais,permissões,cifra/histórico preservados. PDF/PNG/DOCX/XLSX e3WebP com scanClamDreal/hash/recuperação;worker sai após reservar e recupera mesmojob210s depois;repetições sem duplicação. C127:Super requer perfil operacional no âmbito+elevação de consulta independente15min,sem aprovação própria;revogação/novo login e outro dossier recusados. C128:derivadas reutilizadas. UI390px e asset carregado conferidos. A/B,C37 e provas válidas conservadas.
|
||
|
||
Lista única de bloqueios:B1ClamD do destino stale;B2worker/PHPdocumental supervisionados por comprovar no destino;B3dois titulares+terceiro gestorMFA+âmbitos legítimos por designar. Instalações só sob futura autorização;190000 não bloqueia workflow isolado. Restauração e partilha individual permanecem desabilitadas. Candidata/código:{revision[:12]}/{code['code_revision'][:12]},17ficheiros/158assets,`activation_ready=false`. Relatório e procedimento:`outputs/investmoz-workflow-upgrade-20261011/`.
|
||
|
||
Mesma matriz3401requisitos/linhas,7739ocorrências;seteIDs atualizados,zero novos. Backup/restauro REAL do alvo `{target['verified_at']}`:288tabelas/31seq/799ficheiros/2MFA;QA pós-uso `{backup['verified_at']}`:295/31/188/9MFA. Não transformar este restauroQA em prova de funcionamento ativo. Renovar após ajustes/revisão/expiração/antes da intervenção.
|
||
|
||
*As secções seguintes conservam evidências e estados históricos;este bloco contém o estado atual.*
|
||
<!-- /{marker} -->
|
||
'''
|
||
for n in ['relatorio-executivo.md','backlog.md','workflow-criterios-saida-20261011.md','plano-ativacao.md']:
|
||
f=D/n;t=f.read_text(encoding='utf-8');assert marker not in t;first,rest=t.split('\n',1);f.write_text(first+'\n'+brief+rest,encoding='utf-8')
|
||
print(json.dumps(package,ensure_ascii=False))
|