Files
Investidor-V2/tools/portal-audit-update-independent.py
T
nala 01405cbf8a
tests / ci (push) Canceled after 0s
oportunidades 5
2026-10-10 14:15:28 +02:00

403 lines
53 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Reconcile an independent QA increment into the existing audit, preserving its sources."""
import collections
import csv
import hashlib
import json
import re
from datetime import datetime, timezone
from pathlib import Path
import xml.etree.ElementTree as ET
root = Path(__file__).resolve().parent.parent
docs = root / 'docs/investmoz/v2/auditoria-portal'
private = root / 'storage/app/private/investmoz-v2/portal-audit'
target = {'database': 'desk_restore_20261009_174726_test', 'port': 55441}
marker = '[QA independente 10/10/2026] '
def readable(text):
# Format this increment's prose only; retain every identifier/path/hash verbatim.
nouns = ('etapas', 'dossiers', 'limites', 'províncias', 'distritos', 'postos', 'originais', 'geo_locations',
'novas', 'novos', 'privadas', 'públicos', 'públicas', 'referências', 'territórios', 'definições',
'contratos', 'requisitos', 'linhas', 'ocorrências', 'lacunas', 'contextos', 'formulários',
'tabelas', 'ficheiros', 'colunas', 'documentos', 'conversões', 'recursos', 'candidatos', 'nomes',
'definição', 'níveis', 'versões', 'pendentes', 'instâncias', 'geometrias', 'já', 'elementos')
text = re.sub(r'\b([A-Za-zÀ-ú]+)(\d+)(?=(?:' + '|'.join(nouns) + r')\b)', r'\1 \2', text)
text = re.sub(r'(?<![\w-])(\d+)(?=(?:' + '|'.join(nouns) + r')\b)', r'\1 ', text)
text = re.sub(r'\b(servidor|edição|INE|QA|HTTP|total|das|as|os|de|conta|público|baseline)(?=\d)', r'\1 ', text)
text = re.sub(r'(?<=[A-Za-zÀ-ú])\.(?=\d)', '. ', text)
return text.replace('público 0/32.393/393', 'público: 0/32. 393/393')
def read(name):
return json.loads((private / name).read_text(encoding='utf-8-sig'))
def suite(name, expected):
cases = list(ET.parse(private / name).iter('testcase'))
assert len(cases) == expected and all(not list(c) for c in cases), name
return {'junit': name, 'tests': len(cases), 'assertions': sum(int(c.get('assertions', 0)) for c in cases),
'cases': [{'class': c.get('class'), 'method': c.get('name'), 'assertions': int(c.get('assertions', 0))} for c in cases],
'target': 'investmoz_test:55441', 'interface_observed': False}
runtime = read('investor-path-qa-runtime.json')
preservation = read('geometry-crosswalk-preservation-qa.json')
geo_http = read('geometry-crosswalk-consumers-http-qa.json')
catalogue = read('territory-catalogue-coverage.json')
consumers = read('geometry-consumers-path-qa.json')
pdf_types = read('document-types-fixture-qa.json')
resource_http = read('resources-real-http-qa.json')
resource_preservation = read('resource-originals-preservation-http-qa.json')
rotation = read('resource-http-actors-rotation-qa.json')
for p in (runtime, preservation, geo_http, catalogue, consumers):
assert p['target'] == target and p['active_writes'] == 0
assert preservation['catalogue_preserved'] and preservation['catalogue_count'] == 1990
assert preservation['original_geometries_preserved'] == 361 and preservation['total_active'] == 393
assert len(preservation['new_geometries']) == 32 and not preservation['published']
assert not geo_http['applied'] and len(geo_http['consumer_recovery']) == len(geo_http['public_recovery']) == 32
assert len(geo_http['province_name_recovery']) == 2 and not geo_http['interface_observed']
assert [(p['expected'], p['resolved'], p['pending']) for p in geo_http['plans']] == [(11, 11, 0), (159, 128, 31), (411, 254, 157)]
assert catalogue['references_expected'] == catalogue['references_recovered'] == 1920 and catalogue['geometry_rows'] == 393
assert consumers['real_geometries_checked'] == 393 and not consumers['visual_verified']
for p in (resource_http, resource_preservation, rotation):
assert p['target'] == target and p['active_writes'] == 0
assert resource_http['original_pdf_strictly_parseable'] and resource_http['valid_pdf_only_increment'] and not resource_http['new_derivative_scans_performed']
assert resource_preservation['previous_binaries_preserved'] == 5 and resource_preservation['new_pdf_strict_parse'] and not resource_preservation['interface_observed']
assert len(pdf_types['fixtures']) == 2 and all(f['strict_parse'] and f['pages'] == 1 for f in pdf_types['fixtures'])
assert rotation['rotated_synthetic_actors'] == 2 and rotation['mfa_preserved'] and rotation['investor_18_preserved']
suites = [suite('geometry-crosswalk-qa.xml', 7), suite('document-independent-qa.xml', 2),
suite('document-batch-independent-qa.xml', 3), suite('countries-independent-qa.xml', 22),
suite('countries-forms-independent-qa.xml', 4)]
schema_path = root / 'resources/data/investmoz-opportunity-modular.schema.json'
schema_trace = json.loads((root / 'resources/data/investmoz-opportunity-modular.source.json').read_text(encoding='utf-8'))
assert hashlib.sha256(schema_path.read_bytes()).hexdigest() == schema_trace['artifact_sha256']
assert len(json.loads(schema_path.read_text(encoding='utf-8'))['$defs']) == schema_trace['definitions'] == 110
assert not schema_trace['runtime_validation_implemented'] and not schema_trace['workflow_implemented']
matrix = docs / 'matriz-requisitos.csv'
baseline = private / 'matriz-pre-lote-independente-20261010.csv'
if not baseline.exists():
baseline.write_bytes(matrix.read_bytes())
with matrix.open(encoding='utf-8-sig', newline='') as f:
reader = csv.DictReader(f)
columns = reader.fieldnames
rows = list(reader)
protected = ['ID', 'Pedido/trecho', 'Fonte/ocorrências', 'Módulo', 'Rotas', 'Estado', 'Prioridade',
'Critério de aceitação', 'Versões divergentes', 'IDs das linhas de origem',
'Quantidade de linhas de origem', 'Critérios e versões por origem (JSON)', 'Consolidação']
def source_hash(data):
return hashlib.sha256(json.dumps([{k: r[k] for k in protected} for r in data], ensure_ascii=False, separators=(',', ':')).encode()).hexdigest()
before_hash = source_hash(rows)
original_rows = list(csv.DictReader(baseline.open(encoding='utf-8-sig', newline='')))
assert before_hash == source_hash(original_rows), 'Source/identity/state projection changed since this increment.'
counts = read('contagens-requisitos.json')
assert len(rows) == counts['requisitos'] == counts['linhas_matriz'] == 3354
assert sum(int(r['Quantidade de linhas de origem']) for r in rows) == counts['linhas_origem'] == 5830
assert collections.Counter(r['Estado'] for r in rows) == {k: v['requisitos'] for k, v in counts['por_estado'].items()}
updates = {}
def set_evidence(ids, **fields):
for identifier in ids:
updates.setdefault(identifier, {}).update(fields)
geo_proof = ('C38: geometry-crosswalk-http-qa.json + geometry-crosswalk-preservation-qa.json: 32 inseridas privadamente por ação autenticada, '
'361 originais e 1990 geo_locations preservados; 393=11/128/254. geometry-crosswalk-consumers-http-qa.json: '
'32/32 novos limites recuperados pelo endpoint do componente com gestor/MFA, 0/32 divulgados publicamente; duas províncias recuperadas por nome exato. '
'geometry-consumers-path-qa.json: 393/393 contextos READ ONLY; territory-catalogue-coverage.json: 597 consultas, 1920/1920 referências. '
'geometry-crosswalk-qa.xml: correspondências/pai/exemplar/conflitos/idempotência/reversão atómica, incluindo dependência dos descendentes. '
'TypeScript/build preparados; nenhuma renderização observada.')
geo_gap = ('11/11 províncias resolvidas; faltam 31/159 distritos e 157/411 postos do exemplar2019, por nome em correspondencias-cartograficas.md. '
'Cidade De Maputo MZ0601 não equivale a um distrito urbano individual; Mandie MZ040402 tem duas linhas no cadastro. '
'Sem polígonos de localidades neste exemplar. Campos/mapas/preview/aplicação/reversão na interface pendentes; '
'divulgação de camadas separada, nenhuma importação/publicação ativa.')
set_evidence(['AUD-GEO-01', 'AUD-GEO-02', 'AUD-GEO-03'], **{
'Implementação encontrada': 'Correspondências versionadas Maputo Província/Maputo Cidade/Matola vinculadas a exemplar e pai; descendentes exatos; ProvinceSelect resolve nome guardado sem alterar valor e chama TerritoryGeometryPreview.',
'Evidência funcional': geo_proof, 'Lacuna': geo_gap,
'Dependência': 'Correspondência inequívoca por exemplar/pai; revisão visual por consumidor/perfil e publicação separada. C37 não bloqueia desenvolvimento/consulta QA independente.',
'Interface': 'Código dos seletores e mapas preparado; sem aceitação visual. Preserve-se C37 e A/B pendentes.',
'API': 'Endpoint web18097 recupera32/32 novas geometrias para gestor e nenhuma para público; 1920 referências QA recuperadas sem omissões.',
'Gravação': '32 novas geometrias internas por aplicação autenticada, com replay/receipt/auditoria; nenhum geo_location novo; 361 geometrias originais preservadas.',
'Recuperação': '393/393 contextos por serviço; 32/32 novos por endpoint HTTP consumidor. As provas têm escopos separados.',
'Resultado apresentado': 'GeoJSON/props/contexto devolvidos e classificação preservada; mapa/seletor renderizado pendente.'})
set_evidence(['AUD-GEO-04'], **{'Evidência funcional': 'Atualização READ ONLY territory-catalogue-coverage.json: alvo desk_restore_20261009_174726_test:55441;597 consultas/1920 IDs/0omissões. Critério API restrito já demonstrado; não fecha campos/mapas.'})
for row in rows:
if row['ID'].startswith('AUD-FIELD-') and ('<ProvinceSelect' in row['Pedido/trecho'] or row['ID'] in ('AUD-FIELD-004', 'AUD-FIELD-005')):
set_evidence([row['ID']], **{'Implementação encontrada': 'ProvinceSelect partilhado: nome guardado permanece intacto; consulta exata única obtém ID para TerritoryGeometryPreview, sem mapear texto antigo por aproximação.',
'Evidência funcional': 'TypeScript/build; geometry-crosswalk-consumers-http-qa.json comprova duas correspondências por nome e32 contextos novos no endpoint real. Esta prova não certifica gravação/recuperação de cada formulário consumidor.',
'Interface': 'Ligação do componente preparada; apresentação/campo/gravação/recuperação visual individual pendentes.'})
country_proof = ('countries-independent-qa.xml: métodos específicos InvestmentWorkspaceTest(perfil/empresa/manifestação/CRM), '
'PortalAuditContinuationTest(público/quatro apoios/catálogo/Balcão territorial), PortalAuditNextLotTest(negócios/fundiário), '
'PortalOriginCompatibilityTest(origem legada) e InvestorGuidanceTest(Balcão). '
'countries-forms-independent-qa.xml: métodos próprios do interesse público em negócio, jornada da carteira, '
'três serviços Balcão e simulador. Cobertura por formulário em cobertura-percursos-i0-i3.md; '
'a expressão original em nomes de testes também seleciona testes documentais, não contar22 requisitos/percursos de países.')
set_evidence(['AUD-COUNTRY-01', 'AUD-COUNTRY-02', 'AUD-COUNTRY-03', 'AUD-COUNTRY-04', 'AUD-COUNTRY-06', 'AUD-COUNTRY-07', 'AUD-STATS-01'], **{
'Evidência funcional': country_proof,
'Lacuna': 'API/gravação/recuperação/filtros/agregados têm provas por formulário identificado; seleção, feedback, variações condicionais e apresentação de filtros/tabela/nova sessão no navegador continuam pendentes. Não inferir origem da residência/constituição/fiscal/fundos; faltas históricas permanecem Não informado.',
'Interface': 'Componentes já existentes; nenhuma nova confirmação visual neste lote.',
'API': 'Ensaios de rotas reais no kernel QA: códigos ISO inválidos422 sem escrita, replay idempotente, versões409 e acesso indevido403/404, conforme formulário.',
'Gravação': 'Valores separados e revisões/snapshot por formulário, fora da base ativa; rascunhos não contaminam agregados de submissões.',
'Recuperação': 'GET/listas/filtros próprios demonstrados por método; diferente conta recusada. Não equivalem a nova sessão de navegador.',
'Resultado apresentado': 'Recibos/props/JSON/filtros/estatísticas de interests, desk e businesses separados; renderização pendente.'})
set_evidence(['AUD-COUNTRY-05'], **{'Evidência funcional': 'Catálogo ISO independente: método próprio PortalAuditContinuationTest em countries-independent-qa.xml renovado;249 países/pesquisa/paginação. Fecho restrito à API mantém-se, não fecha todos os formulários.'})
document_proof = ('C39: document-independent-before-qa.xml reproduz404 dos originais canónicos cifrados no fundiário e na sala de parceria. '
'document-independent-qa.xml: PDF/PNG/JPEG, scan ClamD real, quarentena, autorização, download cifrado/bytes originais, '
'tamper404, recuperação; partilha autor→candidato, outro perfil403, revogação→404 e eventos persistidos. '
'document-batch-independent-qa.xml: caso real de importação privada/dedup/replay/conflito de identidade/original hash/scan/download/perfis; '
'dois casos antigos são fixtures/queue mock, não prova ClamD. C40: CLI --actor é atribuição, não autenticação; apply recusa ambiente ativo e ator QA sem manage-portal.')
document_proof += (' C41: document-types-fixture-qa.json comprova PDFs sintéticos válidos de1página nos novos testes; '
'resources-real-http-qa.json renova upload/scan real/recuperação de um novo PDF válido no servidor18097, sem substituir antigos; '
'resource-originals-preservation-http-qa.json recupera os5binários anteriores com mesmo SHA, e parseia o novo PDF recuperado. '
'PNG/3WebP anteriores recuperados com assinatura/perfis, sem afirmar novos scans das derivadas. '
'C42: passwords de2atores auxiliaresQA rodadas/remember tokens revogados; MFA e conta18 preservados; nenhum segredo exportado nas novas provas.')
set_evidence(['AUD-LIB-01', 'AUD-LIB-02', 'AUD-SCAN-01', 'AUD-PART-01', 'AUD-LAND-01'], **{
'Evidência funcional': document_proof,
'Lacuna': 'Correções de recuperação cifrada em fundiário/parcerias e lote QA demonstradas por rotas/kernel+DB; não são sessão/browser18097. '
'Continuam renderização PDF/impressão, ações visuais e consumidores/tipos restantes, aplicação de lote por mecanismo ativo autenticado, '
'manutenção/arranque permanente ClamD e GD do PHP ativo. Provas WebP/biblioteca/Balcão anteriores conservadas, não repetidas nem generalizadas.',
'Interface': 'Sem prova visual de leitura PDF, impressão, partilha ou derivadas neste lote.',
'API': 'Fundiário: owner200, outro404; parceria: autor200, candidato só após partilha200, gestor/estranho403, revogada404. Quarentena/tamper404 conforme rota.',
'Gravação': 'size_bytes/uploaded_by preenchidos em novos uploads; partilhas/revogação/leituras auditadas; originais privados e hash preservados, nenhum dado ativo alterado.',
'Recuperação': 'VerifiedDocumentBinary comum decifra e verifica original sem cópia pública; GET com novo contexto de ator recupera estado/permissão. Impressão devolve props200, não PDF renderizado.',
'Resultado apresentado': 'Bytes PDF/PNG/JPEG comparados ao original; estado de partilha recuperado. Interface/PDF visual continuam pendentes.'})
set_evidence(['AUD-OP-02'], **{'Evidência funcional': document_proof,
'Lacuna': 'Recursos instalados somente na QA; novo PDF válido e scans/bytes/perfis/sessão recuperados no servidor18097. Antigos5binários preservados. Renderização PDF/ações na interface pendentes; instalação ativa ainda não efetuada.'})
set_evidence(['AUD-OP-03', 'AUD-OP-04'], **{
'Implementação encontrada': 'Schema normativo §26 conservado em resources/data/investmoz-opportunity-modular.schema.json,110 definições/nove contratos Create/Patch/Response, origem/parágrafos/SHA em .source.json. Não há validação runtime nem workflow integrado novos.',
'Evidência funcional': 'Artefacto parseado/hash conferido contra extração existente da especificação DOCX; seleção de categorias atual não é contrato especializado. QA funcional do workflow/contratos continua ausente.',
'Lacuna': 'Implementar adaptador de IDs existentes, validação modular Create/Patch/gates e estados/transições/permissões/versionamento/revisão/aprovação/publicação separados. Nenhum destes critérios fechado pela extração do schema.',
'Dependência': 'Reutilizar OpportunityManagement/Resources, JSONdraft/version, usuários/policies/audit_events e serviços fundiário/negócio/documentos/territórios. Preparação paralela e decisão externa distinta; não requer CRM externo.',
'Interface': 'Categorias existentes; campos/gates/workflow especializado não implementados.',
'API': 'Contratos normativos preparados; validação/transições especializadas não implementadas.',
'Gravação': 'Nenhuma migration ou alteração de oportunidades deste lote; artefacto não ativa módulos.',
'Recuperação': 'Artefacto legível e rastreável; não existe percurso funcional especializado demonstrado.',
'Resultado apresentado': 'Não implementado funcionalmente; estado canónico mantido.'})
set_evidence(['AUD-OPS-01'], **{
'Evidência funcional': 'Lote independente: geo32novas/393privadas/replay/reversão com dependências; docs/lote QA/perfis. Fingerprints atuais em investor-path-qa-runtime.json; plano-ativacao.md reconciliado. Ready anterior histórico; candidata/ativação falsas.',
'Lacuna': 'C37/A/B/consumidores visuais pendentes; renovar backup/restauro/compatibilidade da candidata final. Ativo não consultado novamente nem alterado; contagens/ledger ativos têm de ser reconfirmados antes de qualquer ação futura.',
'Dependência': 'Recursos030000 se ausentes→percurso190000 se pendente→flag separada. Importação GIS1→2→3 privada; publicação separada; lote documental ativo requer mecanismo autenticado. Nenhum CLI QA pode aplicar no ativo.'})
for row in rows:
for field, value in updates.get(row['ID'], {}).items():
if field == 'Lacuna' or field == 'Dependência':
# Retain the superseded diagnosis as dated evidence, not as a current blocker.
old = row[field].split(marker)[0].rstrip()
if old.endswith(' |'):
old = old[:-2].rstrip()
prefix = 'Histórico até09/10 (preservado): '
if old and not old.startswith(prefix):
old = prefix + old
row[field] = old + (' | ' if old else '') + marker + value
else:
old = row[field].split(marker)[0].rstrip()
if old.endswith(' |'):
old = old[:-2].rstrip()
row[field] = old + (' | ' if old else '') + marker + value
assert set(updates).issubset({r['ID'] for r in rows})
assert before_hash == source_hash(rows)
with matrix.open('w', encoding='utf-8-sig', newline='') as f:
writer = csv.DictWriter(f, fieldnames=columns, lineterminator='\n')
writer.writeheader()
writer.writerows(rows)
def insert(filename, heading, body):
path = docs / filename
text = path.read_text(encoding='utf-8-sig')
begin = '<!-- qa-independent-20261010:begin -->'
end = '<!-- qa-independent-20261010:end -->'
block = begin + '\n' + heading + '\n\n' + readable(body.strip()) + '\n' + end + '\n\n'
if begin in text:
start = text.index(begin)
finish = text.index(end, start) + len(end)
text = text[:start] + block + text[finish:].lstrip('\n')
else:
first = text.index('\n')
text = text[:first + 1] + '\n' + block + text[first + 1:].lstrip('\n')
path.write_text(text, encoding='utf-8')
history_note = '**Versões anteriores preservadas:** as secções abaixo documentam os instantes anteriores.361 e2/39/179 são a baseline09/10; o estado cartográfico corrente deste lote é393 e0/31/157. Ready/hashes/contagens antigas não certificam esta revisão. C37 mantém a sua confirmação visual pendente, sem bloquear as frentes independentes.'
state_table = '\n'.join(f"| {k} | {v['requisitos']} | {v['linhas_origem']} |" for k, v in counts['por_estado'].items())
executive = f'''QA exclusiva: http://127.0.0.1:18097; alvo confirmado `{target['database']}:55441`. Testes de feature usam outra QA, `investmoz_test:55441`, com guarda antes de qualquer escrita. Sem alterações, instalação, importação ou publicação na base ativa. Cinco fases/19etapas preservadas;5dossiers/95etapas na QA web, sem criação de jornadas educativas.
| Requisito | Entrega e prova | Critérios ainda abertos |
| --- | --- | --- |
| AUD-GEO-01/02/03; C38 | Correspondências explícitas Maputo Província, Maputo Cidade e Matola; descendentes por nome exato+pai. Ação autenticada/MFA no servidor18097 insere32limites internos:2províncias+8distritos+22postos.361originais e1990geo_locations preservados.32/32 novos recuperados via endpoint consumidor; público0/32.393/393 contextos por serviço;1920/1920referências territoriais por API. ProvinceSelect liga o nome guardado ao preview sem reescrever valores. |31distritos/157postos por nome; localidades sem polígonos neste exemplar; integração renderizada por consumidor e ato de divulgação separados. |
| AUD-COUNTRY-01–04/06–07, STATS-01 | Provas renovadas por método/formulário: perfil/empresa/manifestação/público/quatro apoios/carteira/interesse público em negócio/wizard/fundiário/três Balcões/simulador/CRM. Gravação→GET→filtro→agregado quando aplicável; residência/constituição/fiscal/fundos distintos da origem declarada; unknown preservado. |Seleção, recibos, variações condicionais, filtros/tabela e nova sessão na interface. Não contar testes documentais selecionados pela palavra original como requisitos de países. |
| AUD-LAND-01, PART-01, LIB-01/02, SCAN-01; C39/C40 |404 dos originais cifrados corrigido em fundiário e sala de parceria por VerifiedDocumentBinary comum; novos uploads registam tamanho/autor. PDF/PNG/JPEG com ClamD real, hash, quarentena/perfis/partilha/revogação/adulteração/recuperação. Lote documental QA privado, idempotente, sem substituir identidade conflituosa; actor sem permissão/ambiente ativo recusados. |Renderização PDF/impressão, ações visuais e restantes consumidores/tipos; lote ativo autenticado. Serviço ClamD real demonstrado separado de arranque/manutenção permanente/GD ativo. |
| AUD-OP-02/SCAN-01; C41/C42 |PDFs sintéticos apenas com cabeçalho não provavam legibilidade: novos testes usam PDF válido de uma página, parseado independentemente. No servidor18097, novo PDF anexado à oportunidadeQA12→scan real→download→nova sessão→recuperação; outra conta403. Cinco binários anteriores preservados por SHA; PNG/3WebP recuperados, sem novo scan das derivadas. Credenciais fixas do script removidas; passwords/remember tokens de dois atoresQA auxiliares rodados; MFA/conta18 preservados. |PDF renderizado e interface documental pendentes. O placeholder anterior permanece conservado como evidência e não certifica abertura de PDF. |
| AUD-OP-03/04 |Schema normativo §26 preparado e rastreável:110definições,9contratos Create/Patch/Response, sem renumerar IDs. |Workflow e validação/gates especializados continuam não implementados; nenhum fecho funcional atribuído ao artefacto. |
| C37, AUD-UI-01, I1–I3 |Evidências anteriores conservadas, nenhum novo ensaio de login investidor neste lote. |Login/reload/logout/nova sessão e A/B completos na interface continuam pendentes. |
| Nível INE2019 | Esperado no exemplar | Resolvido QA | Pendente |
| --- | ---: | ---: | ---: |
| Província |11|11|0|
| Distrito |159|128|31|
| Posto |411|254|157|
| Total |581|393|188|
Os denominadores da edição2019 não são os1920territórios do cadastro existente. [188lacunas por nome](correspondencias-cartograficas.md), incluindo Cidade De Maputo agregado e Mandie duplicado no próprio workbook; nenhuma equivalência por código/fuzzy, nem fusão de cadastros. Aceitação das fontes oficiais preservada.
**Mesma matriz, sem requisitos amplos recém-fechados:**3354requisitos/3354linhas canónicas;5830ocorrências de origem. IDs, fontes, trechos, diferenças de versão, critérios e estados conservados.
| Estado | Requisitos/linhas | Ocorrências |
| --- | ---: | ---: |
{state_table}
Evidências privadas: `geometry-crosswalk-http-qa.json` (aplicação posterior22, além das2+8 anteriores registadas na auditoria), `geometry-crosswalk-preservation-qa.json` (total32novas), `geometry-crosswalk-consumers-http-qa.json` (HTTP32novas/0públicas), `geometry-consumers-path-qa.json` (serviço393), `territory-catalogue-coverage.json` (catálogo1920). Não confundir aplicação parcial inicial interrompida por Mandie com duplicação: as10já aplicadas foram reutilizadas na continuação; ambiguidade nominal fica pendente e não bloqueia outras correspondências únicas.
Testes dirigidos: `geometry-crosswalk-qa.xml` (casos de vínculo/pai/exemplar/conflito/replay/reversão), `document-independent-qa.xml` (dois percursos PDF/PNG/JPEG/perfis), `document-batch-independent-qa.xml` (um caso ClamD real; dois de fixture), `countries-independent-qa.xml` e `countries-forms-independent-qa.xml` (métodos identificados na [cobertura](cobertura-percursos-i0-i3.md)). TypeScript/build/PHPStan dos componentes alterados passaram. A guarda de concorrência recusou um arranque paralelo de testes; ficou em `countries-forms-independent-lock-refusal-qa.xml`; o ensaio sequencial posterior passou. Isto é tooling protegido, não falha de formulário.
Complemento documental: `document-types-fixture-qa.json`, `resource-originals-preservation-http-qa.json`, `resource-http-actors-rotation-qa.json` e nova versão de `resources-real-http-qa.json`; versão anterior arquivada antes da atualização. Credenciais novas somente no ficheiro privado local; nenhum cookie/OTP/body exportado. Não alterar os originais anteriores para tornar o ensaio verde.
Código preparado e QA API/persistência demonstradas neste âmbito; interface não demonstrada. `candidate_revision_fixed=false`, `integrated_ui_ab_passed=false`, `activation_ready=false`. [Backlog atual](backlog.md) e [ordem de ativação/reversão](plano-ativacao.md). Não há candidata final nem novo backup final de ativação emitido.
{history_note}'''
insert('relatorio-executivo.md', '## Lote independente I0–I3 — 10/10/2026', executive)
insert('execucao-percurso-i1-i3.md', '## Lote independente I0–I3 — 10/10/2026', executive)
backlog = f'''Não aguardar C37 para executar os itens independentes. C37/P0 conserva a confirmação visual do login e cenáriosA/B; nenhuma nova tentativa solicitada neste lote.
| Prioridade / requisito | Próxima correção executável e componentes | Dados/dependência concreta | Aceitação |
| --- | --- | --- | --- |
| P1 GEO-02/03; C38 |Resolver31distritos/157postos com crosswalk versionado por fonte/edição/pai; reutilizar geo_locations/geo_geometries, TerritoryGeometryImport/Preview/Fields/ProvinceSelect. Conferir todos os consumidores na lista existente. |Exemplar/linha que distingue Cidade De Maputo agregado e Mandie2linhas; restantes188nomes no relatório. Sem polígonos de localidade disponíveis no exemplar retido. Fonte aceite não exige nova certificação. |Prévia mostra origem/pai/candidato único; aplicar/replay0duplicados/GETresultado; mapa e campo guardar/reabrir/limpar descendentes respeitam perfil; sem divulgar limites privados automaticamente. |
| P1 COUNTRY01–04/06–07, STATS01 |Verificar os seletores/validações condicionais ainda não demonstrados na interface, por formulário da cobertura; corrigir qualquer lacuna executável API/persistência adicional. Reutilizar249ISO, DeclaredOriginStatistics e payloads existentes. |Backend específico renovado; não inferir origem da residência/fiscal/fundos. Valores antigos sem origem ficam desconhecidos. |POST/GET/nova sessão/filtro/tabela/estado vazio próprios; ZZ422sem escrita, revisão409, outra conta403/404; conjuntos interests/desk/businesses separados. |
| P0/P1 documental LAND01/PART01/LIB01–02/SCAN01; C39/C40 |Prosseguir restantes consumidores/tipos/perfis, renderização PDF/impressão e derivadas próprias; reutilizar VerifiedDocumentBinary, documents, scanner/jobs e auditoria. Implementar aplicação documental ativa autenticada antes de futura importação ativa; CLI permanece QA-only. |PDF/PNG/JPEG/fundiário/parceria e loteQA têm prova real; oportunidades PDF/PNG/3WebP e biblioteca/Balcão conservam provas anteriores. Arranque/reboot/assinaturas ClamD e GD PHPativo são pendências operacionais específicas. |Permissão antes dos bytes; scan do hash de cada original/derivada; original preservado; partilha/revogação recuperadas; incorreto/quarentena recusados; PDF efetivamente visível e impressão correta. Não generalizar prova de um consumidor. |
| P1 OP03/04; C08 |Implementar adaptador do schema normativo110defs para OpportunityManagement/management_draft/version; validar Create/Patch por módulo antes de novas transições. Reutilizar OpportunityResources, serviços negócio/fundiário/documentos/territórios e audit_events. Em seguida revisão/devolução/aprovação/publicação com segregação autor/revisor/aprovador e versão aprovada. |Contratos9preparados; UUID de exemplo não renumera bigint. Estado fiscal/jurídico/decisão externa distintos de validação interna. Perfis adicionais exigem contrato aprovado da especificação, não campos inventados. |Rascunho incompleto permanece guardável; revisão precisa indica campo/regra/fonte; transição indevida403/422/409; alteração material invalida apenas aprovação da versão afetada; reviewer não se autoaprova; publicação separada; GET/auditoria/replay preservam IDs/história e permissões. |
| P0 visual C37 + I1–I3 |Manter ensaio manualA/B existente em18097 com MFA sintético, sem credenciais na documentação. Incorporar cada resultado e corrigir falhas antes de fixar candidata. |Confirmar conta18 no MFA e recuperar novo cookie/session sem alterar chave nem conta13. Não bloqueia tarefas independentes acima. |A/B criação→gravação→nova sessão→aplicabilidade→ferramenta→resultado no dossier→Balcão→acompanhamento; tarefa paralela, ausência de mistura/acesso indevido;19etapas/5fases mantidas. |
| P1 OPS01 |Após critérios visuais e correções, fixar revisão e renovar backup/restauro/compatibilidade; gerar provas verdadeiras para a ordem consolidada. |Ativo fora da autorização; confirmar ledger/contagens atuais por leitura futura, não repetir instalações. |Recursos030000/percurso190000/flag/importação1→2→3/publicação separados; reversão GIS3→2→1 preserva catálogo/originais/receipts e recusa descendentes/uso/publicação. |
Concluído neste lote apenas o âmbito específico demonstrado por prova:32correspondências, recuperação documental cifrada e controlos do loteQA; nenhum requisito transversal inteiro encerrado. Workflow/contratos preparados documentalmente continuam não implementados funcionalmente. Cinco fases/19etapas e acesso direto a ferramentas preservados; nenhuma nova jornada educativa. [Matriz única](matriz-requisitos.csv), [evidências por consumidor](cobertura-percursos-i0-i3.md) e [plano](plano-ativacao.md).
Complemento C41: novo PDF válido de1página já gravado/escaneado/recuperado no servidor18097, com5binários anteriores preservados. O placeholder antigo não é prova de renderização; no ensaio visual usar o novo recurso identificado em resources-real-http-qa.json, sem substituir/apagar o antigo. C42 retirou passwords fixas do script e rodou os dois atoresQA auxiliares; manter leitura das credenciais somente no ficheiro privado local, sem enviar na conversa. Não afeta conta18/MFA/C37.
{history_note}'''
insert('backlog.md', '## Backlog corrente do lote independente — 10/10/2026', backlog)
activation = f'''Plano preparado para futura autorização; nenhuma ação ativa executada. Revisão não candidata: percurso `{runtime['code_hash']}`, cartografia `{runtime['geometry_code_hash']}`, recursos `{runtime['resource_code_hash']}`. `ready=true` antigo representa outra preparação e não instalação/conclusão.
| Ordem | Ação futura | Dependência/efeito previsto | Reversão |
| --- | --- | --- | --- |
|0|Concluir critérios visuaisA/B, C37 e consumidores; corrigir falhas e fixar commit/assets/fingerprints.|Provas de API/persistência não substituem interface. Não há candidata final agora.|Corrigir/revalidar só critérios afetados; preservar provas anteriores.|
|1|Renovar backup de DB+ficheiros privados/chaves/originais/metadados e restaurar em nova QA loopback*_test:55441.|Guarda antes da escrita; comparar schema/IDs/relações/hashes/classificações/RLS/ficheiros.288tabelas/5ficheiros são histórico09/10, não contagem a forçar. Provas de reversão/compatibilidade da candidata.|Nunca sobrescrever escritas posteriores sem reconciliação. Restauro ativo permanece fora desta autorização.|
|2|Disponibilizar código/assets/configuração mantendo INVESTOR_PATH_ENABLED=false e TERRITORY_GEOMETRY_IMPORT_ENABLED=false.|Correções países/documentos/seletores não criam nem reclassificam dados por deploy. ClamD/GD somente nas operações binárias afetadas.|Rollback de código compatível preservando payloads novos/originais. CLI documents:import-batch --apply continua recusado no ativo.|
|3|Gestor ativo autorizado: GET/POST /management/opportunity-resources-install **somente se030000ausente**.|Prévia/backup/hash/autorização atuais;3tabelas de associação+1coluna documents+função/3triggers;0documentos/recursos/geometrias criados automaticamente. Não repetir instalações básicas.|Down somente vazio; após uso preservar dados/originais e desligar disponibilização em vez de apagar.|
|4|GET/POST /management/balcao-install somente para migrations pendentes, prevista190000.|2colunas+1definição imutável;0conversões/dossiers/etapas automáticas. Prova A/Bvisual atual exigida.19etapas/5fases e roteiros legados preservados.|Down recusa após uso; desabilitar flag mantendo definição/dossiers/história.|
|5|Habilitar INVESTOR_PATH_ENABLED em ação separada, após schema e aceitação.|Mostra percurso;19etapas somente ao criar dossier novo; ferramentas diretas/URLs/IDs permanecem.|Flagfalse, sem apagar dossier/resultados/documentos/tarefas/consentimentos.|
|6|Preparar prova específica cartográfica vinculada ao fingerprint/alvo/backuprestaurado/UI; habilitar rota separadamente; gestor/MFA GET /management/territory-geometry-import?level=1 → POST, depois2, depois3.|Cada prévia deve conservar exemplar/hash/scan/crosswalk/pai/conflitos. **Se ativo continuar0 e mesmas correspondências únicas:393=11+128+254 novas internas**,0geo_locations/locais/perímetros de investimento.31/157pendentes de fora. QA393inclui32novas e361preservadas; replay0novas. Scan vencido exige renovar prova por bytes, sem reabrir aceitação oficial.|POST /management/territory-geometry-import/{{batch}}/reverse com MFA/razão/idempotência; **postos→distritos→províncias**. Recusa descendentes ativos da edição mesmo sem FK, uso/alteração/publicação; só exclusão lógica de novos intactos não usados. Preservar reutilizados/catalogue/hash/histórico.|
|7|Divulgar camadas por consumidor/âmbito autorizado em ação separada.|Importador não publica. Limites administrativos não são DUAT/perímetro do investimento; não transformar internal em public para passar ensaio. Mecanismo de divulgação de limites administrativos continua a concretizar conforme política existente.|Retirar camada/autorização sem eliminar geometrias/originais/relações.|
Aplicação documental em lote no ativo exige mecanismo autenticado próprio, ainda pendente; o comando existente serve prévia e ensaio isoladoQA. Não adicionar esse lote à sequência ativa como se nomear --actor autenticasse. Schema/workflow especializado preparado não integra estas migrations nem é ativado por elas; sua futura revisão deve ter provas e plano próprios no mesmo backlog.
ClamD real e tipos/derivadas já demonstrados mantêm suas provas; arranque após reboot, assinaturas e PHPativo/GD são critérios específicos em aberto. Importação/publicação não ativa nenhum cálculo fiscal. [Relatório](relatorio-executivo.md) / [backlog](backlog.md).
{history_note}'''
insert('plano-ativacao.md', '## Sequência corrente reconciliada — 10/10/2026', activation)
coverage = '''QA web desk_restore_20261009_174726_test:55441 e ensaios separados investmoz_test:55441. C37/login investidor e A/B visuais continuam pendentes. Nenhuma sessão de navegador foi certificada; a nova autenticação HTTP deste lote foi do gestor cartográficoQA, distinta do investidor18.
**Países — provas renovadas por formulário na tabela existente abaixo:** countries-independent-qa.xml contém os métodos InvestmentWorkspaceTest (perfil/empresa/manifestação/CRM), PortalAuditContinuationTest (manifestação pública/quatro tipos de apoio/catálogo/Balcão territorial), PortalAuditNextLotTest (wizard negócios e fundiário), PortalOriginCompatibilityTest (origem legada) e InvestorGuidanceTest (Balcão). countries-forms-independent-qa.xml contém especificamente BusinessMarketplacePublicTest::test_interest_is_limited_to_published_business_and_deduplicated_idempotently, InvestmentPortfolioTest::test_personal_journey_is_isolated_and_retries_do_not_duplicate_interest_or_event, PortalAuditConsumerLotTest::test_all_three_desk_forms_save_recover_countries_and_support_authorized_corrections e PortalAuditContinuationTest::test_simulator_recovers_iso_countries_in_private_draft_without_reinterpreting_legacy_values. A contagem22inclui outros testes pela palavra original; não representa22formulários/requisitos de países. Cada linha abaixo mantém critérios visuais próprios abertos.
**Cartografia — três estados:** cadastro1920referências/1990geo_locations incluindo70países; geometria administrativa393/581da edição2019; apresentação renderizada não verificada. geometry-crosswalk-consumers-http-qa.json recupera32novos limites por endpoint gestor e0públicos, nomes guardados de ambas as províncias Maputo correspondem a um IDúnico. geometry-consumers-path-qa.json recupera393por serviço. ProvinceSelect partilhado liga este IDao preview e conserva texto antigo desconhecido; isso prepara PortalInvestidor/portal-services/AI, sem alegar resultado visual individual. TerritoryFields/territory-preview/MapaBolsa/InvestmentMapPanel existentes reutilizados. Localidade pode ter contexto ancestral, nunca polígono próprio inferido. Correspondências0/31/157pendentes; todas188nominais no relatório.
| Consumidor/tipo | Prova de operação/perfil/persistência | Limite da prova |
| --- | --- | --- |
| Fundiário PDF |Upload privado→quarentena404→ClamDreal/hash→owner200→original canónico cifrado recuperado por bytes; outro/manager404; GETestado; impressão props200; tamper404; leitura auditada.|IndependentDocumentOperationsTest, iterador próprioPDF; não PDFrenderizado/browser18097.|
| Fundiário PNG |Mesmo percurso, iteradorPNGreal; bytes/hash/scan próprios e size_bytes/uploaded_by.|Não prova renderização visual.|
| Fundiário JPEG |Mesmo percurso, iteradorJPEGreal; bytes/hash/scan próprios e permissões.|Não prova qualquer conversão/derivada não executada.|
| Sala parceria PDF |Autor200/candidato404→partilha autoria persistida→candidato200→novo contexto auth/GETlista→revogação404; candidato não partilha403; gestor/estranho403; scan originalreal/tamper404.|Método próprio com iteradorPDF; novo contexto de autenticação em teste, não sessão nova de navegador.|
| Sala parceria PNG |Mesmo percurso, iteradorPNGreal, partilha/revogação/eventos próprios, original cifrado preservado.|Interface da sala pendente.|
| Sala parceria JPEG |Mesmo percurso, iteradorJPEGreal, original/hash/scan próprios.|Não certifica acordo jurídico externo nem todos os anexos existentes.|
| Lote biblioteca PDF |ImportDocumentBatchTest::test_qa_batch_real_scan_preserves_original_replay_identity_conflict_and_profile_guards: actorQAsem permissão/ambiente ativo recusados; bytes duplicados→um original privado; ClamDreal; gestor200/público404; replay0novos; conflito mesma identidade/bytes diferentes não substitui original.|CLIQA, não mecanismo autenticado de aplicação ativa. Dois testes antigos do ficheiro usam fixture/Busfake.|
| Oportunidades PDF/PNG/3WebP |resources-real-http-qa.json renovado: novo PDF válido→upload/scan/download/logout/nova sessão/403outra conta. resource-originals-preservation-http-qa.json preserva5binários anteriores e confirma uma página do novo PDF baixado; PNG/3WebP assinados recuperados.|Novo scan real somente do novo PDF; scans das derivadas anteriores conservados. Nenhum ensaio visual.|
| Biblioteca/Balcão |document-consumers-real-qa.xml e provas anteriores de bytes/MIME/CSP/scan/perfil conservadas; ensaio de loteQA deste lote separado.|PDFview bytes/CSP não é renderização, nem demonstra validade de todos os fixtures antigos.|
Fundiário e parceria agora reutilizam VerifiedDocumentBinary, sem relaxar permissões nem duplicar documents. Nenhum original foi convertido em cópia pública; novos uploads registam autor/tamanho. Document-independent-qa.xml e document-batch-independent-qa.xml distinguem scanner real de fixture. Arranque permanente ClamD/assinaturas/GDativo permanecem separados das operações demonstradas.
**C41 — validade de PDF também é critério próprio:** os novos testes fundiário/parceria/lote utilizam SyntheticDocument::pdf, parseado por ferramenta independente (document-types-fixture-qa.json: uma página/texto). O placeholder PDF histórico09/10 só tinha cabeçalho/terminador: seus scans/hashes são provas de bytes, não de legibilidade. Sem substituí-lo, resources-real-http-qa.json agora demonstra um novo PDF válido no servidor18097 (upload/ClamD/download/logout/nova sessão/403outra conta). resource-originals-preservation-http-qa.json recupera os5binários anteriores por hash e parseia o novo PDF baixado. PNG/3WebP assinados recuperados outra vez, mas scans das derivadas são os anteriores, sem novo scan inventado. Renderização do novo PDF continua pendente.
**C42 — credenciaisQA:** dois atores auxiliares do script antigo tinham passwords fixas que apareceram na leitura do código; foram rodadas apenas na baseQA, remember tokens revogados e valores fixos retirados do script. Nenhuma sessão alvo restante encontrada para apagar. MFA e a linha inteira da conta18 preservados; chave/configuração ativa não alteradas. resource-http-actors-rotation-qa.json contém somente contagens/flags, sem passwords/cookies/OTP.
Workflow/contratos:110defs/9contratos normativos preparados, runtime_validation_implemented=false/workflow_implemented=false/qa_activation=false; não existe percurso completo novo a certificar. Roteiros19etapas/5fases conservados. Provas e contagens da matriz em relatorio-executivo.md.
'''
insert('cobertura-percursos-i0-i3.md', '## Evidência independente por consumidor — 10/10/2026', coverage + '\n\n' + history_note)
cases = '''### C38 — correspondências provinciais impediam descendentes; ambiguidade nominal bloqueava lote independente — P1
Requisitos AUD-GEO-01/02/03. Reproduzir préviaQA com o exemplarINE2019 e cadastro aceites: Maputo/Maputo City não correspondem literalmente a Maputo Província/Maputo Cidade; Cidade Da Matola não corresponde a CIDADE DE MATOLA. Esperado: equivalência explicitamente versionada por exemplar/pai, sem alterar nomes/códigos/IDs/hierarquia. Observado baseline9/120/232 e2/39/179pendentes; descendentes sob os pais Maputo ficam não resolvidos. Causa: correspondência apenas nominal exata, sem crosswalk dessas variantes concretas.
Correção: três entradas explícitas com códigos de ambos os sistemas preservados, hash do exemplar/workbook e pai obrigatórios. Descendentes exatos tornam-se elegíveis; via gestor/MFA/importação18097 foram inseridas2províncias+8distritos; primeira execução ficou interrompida na prévia de postos por Mandie com2candidatos do cadastro. A classificação inicial correspondence_conflict bloqueava outros postos inequívocos. Corrigida para ambiguous_name pendente quando são nomes iguais sem crosswalk explícito; conflitos de uma correspondência explícita continuam impeditivos. Continuação reutiliza as10anteriores e insere22postos, sem repetir originais. Mandie corresponde a duas linhas reais do workbook e não foi fundido/escolhido por código presumido.
Evidência: preservationQA393/32novas/361originais/1990catalogueigual; HTTPconsumidores32gestor/0públicos; sete casos QAincluem edição/pai/conflictos/replay/reversão3→2→1e recusa de pai com descendente ativo sem FK. Prévia e mapas na interface pendentes. Lacunas0/31/157,188nomes listados; CidadeDeMaputo agregado não é um distrito urbano individual. Ativo não alterado.
### C39 — fundiário e sala de parceria recusam404 um original cifrado íntegro — P0 de recuperação
Requisitos AUD-LAND-01/PART-01/SCAN-01. QA de feature: criar caso fundiário/sala próprios; anexar PDF/PNG/JPEG, completar scan real/hash; reutilizar o mesmo documents canónico com storage_encryption Laravel e bytes cifrados privados; pedir GET /investidor/terra-duat/{id}/documentos/{attachment} ou /parcerias/salas/{id}/documentos/{attachment} pelo ator autorizado. Esperado200 com bytes originais, preservando autorização/scan/hash. Observado404 nos dois consumidores, reproduzido em document-independent-before-qa.xml. Causa: hash do ciphertext comparado diretamente ao SHA do original e binário devolvido sem VerifiedDocumentBinary.
Correção: serviço comum de decifragem/integridade/quarentena; selecionar metadata cifragem sem expor chave; conservar autorização original. Novos uploads registam size_bytes/uploaded_by antes ausentes, leituras fundiárias em audit_events existente. Evidência pós-correção: document-independent-qa.xml, PDF/PNG/JPEG originais reais/ClamD/perfis/partilha/revogação/GET/tamper404. Impressão apenas props200; renderizaçãoPDF/browser pendentes. Nenhum ciphertext/segredo exportado, nenhum original substituído/publicado, nenhuma migration/dado ativo alterado.
### C40 — --actor não comprova autorização nem autenticação de lote documental — P1
Requisitos AUD-LIB-02/OPS-01. Identificado por revisão do comando documents:import-batch: --actor antes só exigia IDexistente, sem can:manage-portal nem guarda de alvoQA para --apply. Não houve execução ativa nem alegação de exploração ativa. Esperado: ensaio de escrita isoladoQA com ator autorizado; aplicação ativa somente autenticada pelo mecanismo previsto. Correção: environmenttesting+SQLreal*_test:55441+loopback+URLvazia e User::can('manage-portal') antes de escrita. Ambienteproduction recusado mesmo apontado a uma baseQA; nomear ator não autentica.
document-batch-independent-qa.xml demonstra recusas sem DB/ficheiros novos, prévia privada/replay/dedup/hash/ClamDreal/perfis e conflito de identidade sem substituição. Aplicação documental ativa autenticada continua pendente; não adaptar CLIpara o ativo. Este limite não impede os ensaiosQA nem consulta/read-only. Nenhuma publicação automática.
### C41 — PDF sintético com cabeçalho não comprova legibilidade — lacuna de QA
Requisitos AUD-SCAN-01/OP-02. Revisão do fixture histórico de portal-resources-real-http-qa.py encontrou apenas cabeçalhoPDF e terminador; parser independente recusa-o sem startxref/estrutura. Esse ensaio demonstra upload/scan/hash/download dos bytes, não PDF legível ou renderizado. Não é diagnóstico de um documento oficial nem falha presumida do leitor do portal.
CorreçãoQA: gerador sintético válido de1página, árvore de objetos/xref/texto; parser independente confirma original e variante de lote. Novos testes fundiário/parceria/lote reexecutados com esses bytes/ClamDreal. Anexado um novo recurso válido à oportunidade sintéticaQA12 no servidor18097; original placeholder e PNG/3WebP anteriores preservados por hash, sem repetir instalação nem criar oportunidade/cartografia/jornada duplicada. Novo PDF download/ClamD/403outra conta/logout/nova sessão/recuperação passaram. Evidências document-types-fixture-qa.json/resources-real-http-qa.json/resource-originals-preservation-http-qa.json. Renderização visual PDF/impressão continua pendente.
### C42 — passwords fixas de atores sintéticos no scriptQA — corrigido, sem exposição ativa
Durante a leitura de um script legado apareceram passwordsQA fixas. Correção imediata com portal-resource-http-actors-qa.php e guarda real do destino: dois atores sintéticos auxiliares, passwords aleatórias privadas e remember tokens rodados. Diretório de sessõesQA validado; nenhuma sessão desses atores restante para invalidar. MFA mantido byte a byte, conta18 preservada por hash da linha; nenhuma chave/conta/dado ativo alterado. ScriptHTTP passa a ler credenciais do ficheiro privado local; suporte a MFA normal permanece. Não repetir valores, cookies ou OTP em prova/captura. Evidência sanitizada resource-http-actors-rotation-qa.json; login/logout/nova sessão dos perfis auxiliares demonstrados no servidor pelo lote documental, separados do C37 investidor.
'''
insert('casos-reproducao.md', '## Casos adicionais do lote independente — 10/10/2026', cases)
dashboard = '''[Estado corrente na matriz existente](auditoria-portal/matriz-requisitos.csv), [relatório](auditoria-portal/relatorio-executivo.md) e [backlog](auditoria-portal/backlog.md):3354requisitos/5830origens;32geometrias adicionaisQA,393privadas no total; correspondências11/128/254 e lacunas0/31/157. Recuperação documental cifrada fundiário/parceria e loteQA demonstrados por operações específicas; países/origem renovados por formulário. Schema especializado110defs/9contratos preparado com fonte/hash, ainda sem validaçãoruntime/workflow integrado. Maturidade7/8 no draft foi corrigida em lote posterior ao texto histórico abaixo, sem reinterpretar seis valores legados; isso não conclui publicação/workflow. C37 e A/Bvisuais continuam pendentes. Recursos ativos não instalados no último retrato conhecido, a reconfirmar antes de futura ação; ready/hashes antigos não representam a revisão atual. Nenhuma alteração ativa. Cinco fases/19etapas e URLs/IDs/cadastros preservados.
As atualizações datadas09/10e entregas abaixo permanecem como histórico, incluindo falhas/contagens posteriormente corrigidas; prevalecem os critérios/evidências atuais do relatório e da mesma matriz.'''
path = root / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md'
text = path.read_text(encoding='utf-8-sig')
begin, end = '<!-- qa-independent-20261010:begin -->', '<!-- qa-independent-20261010:end -->'
block = begin + '\n## Estado corrente — 10/10/2026\n\n' + readable(dashboard) + '\n' + end + '\n\n'
if begin in text:
start = text.index(begin); finish = text.index(end, start) + len(end)
text = text[:start] + block + text[finish:].lstrip('\n')
else:
first = text.index('\n'); text = text[:first + 1] + '\n' + block + text[first + 1:].lstrip('\n')
path.write_text(text, encoding='utf-8')
proof = read('investor-path-evidence.json')
proof.setdefault('historical_revision_before_independent_increment', {k: proof.get(k) for k in ('captured_at', 'code_hash', 'geometry_code_hash', 'resource_code_hash', 'qa_demonstrated')})
proof.update(runtime)
proof.update({'candidate_revision_fixed': False, 'integrated_ui_ab_passed': False, 'activation_ready': False,
'c37_browser_acceptance_passed': False, 'independent_qa_increment': {'date': '2026-10-10', 'suites': suites,
'geometry_preservation': 'geometry-crosswalk-preservation-qa.json', 'geometry_consumers_http': 'geometry-crosswalk-consumers-http-qa.json',
'valid_pdf_http': 'resources-real-http-qa.json', 'originals_preservation_http': 'resource-originals-preservation-http-qa.json',
'pdf_fixture_types': 'document-types-fixture-qa.json', 'auxiliary_qa_credential_rotation': 'resource-http-actors-rotation-qa.json',
'specialized_schema': schema_trace, 'current_revision_full_ab_demonstrated': False, 'interface_observed': False, 'active_writes': 0},
'qa_demonstrated': 'Independent increment: authenticated cartography HTTP/DB and per-consumer feature routes/DB. Historical A/B HTTP retained; current integrated browser A/B not demonstrated.',
'current_revision_full_suite_demonstrated': False,
'full_suite_scope': 'Historical suite before this independent increment; use the named current selected cases, not its global count, to assess current criteria.',
'current_active_backup_compatibility_renewal_required': True})
(private / 'investor-path-evidence.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
matrix_proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'target': target, 'matrix': str(matrix.relative_to(root)),
'requirements': len(rows), 'source_occurrences': 5830, 'rows': len(rows), 'updated_ids': list(updates),
'protected_projection_sha256_before': before_hash, 'protected_projection_sha256_after': source_hash(rows),
'sources_versions_ids_criteria_states_preserved': True, 'states': counts['por_estado'],
'source_conservation_sha256_retained': counts['conservation_sha256'], 'active_writes': 0,
'interface_observed': False, 'candidate_revision_fixed': False}
(private / 'independent-increment-matrix-qa.json').write_text(json.dumps(matrix_proof, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps({'requirements': len(rows), 'source_occurrences': 5830, 'updated_requirements': len(updates), 'states_unchanged': True,
'geometry_total': 393, 'geometry_inserted': 32, 'pending_by_level': [0, 31, 157], 'visual_verified': False, 'active_writes': 0}, ensure_ascii=False))