Files
Investidor-V2/tools/portal-audit-delivery-lote2.py
T
nala 6ddafc95ba
tests / ci (push) Canceled after 0s
oportunidades 4
2026-10-10 07:03:59 +02:00

266 lines
35 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.
"""Update the existing audit documents; retain previous accounts as history."""
from pathlib import Path
import json
root = Path(__file__).resolve().parent.parent
docs = root / 'docs/investmoz/v2/auditoria-portal'
proof = root / 'storage/app/private/investmoz-v2/portal-audit'
report = '''# InvesteMoz — relatório executivo do lote 2
09/10/2026. Continuação da **mesma matriz**. Código preparado, API/persistência demonstradas em QA e funcionalidade ativa são estados separados. **Nenhuma escrita de dados na base ativa por esta auditoria.** Leitura ativa: 17:20:47 UTC. Navegador indisponível: a tentativa de abrir QA voltou a falhar; não há demonstração visual desta versão.
## Resultado e prioridades
As três falhas anteriormente classificadas foram corrigidas no âmbito ensaiado: rejeição 422 da maturidade 7/8, indisponibilidade do ClamD e checks globais de formato. Isto não encerra os requisitos mais amplos de maturidade/publicação, binários/derivadas ou interface. Foram ainda encontrados e corrigidos a rejeição da hierarquia territorial fundiária, a perda da origem ao solicitar apoio e o botão de pesquisa sem ação.
| Requisito / caso | Correção e evidência | QA / ativo |
| --- | --- | --- |
| AUD-OP-05 / C15 | Oito etapas versionadas; 7/8 recebem 201 e GET recupera etapa/posição/versão. Legado de seis níveis mantém significado; discrepância 422, conflito 409, outro utilizador 403. | API/persistência QA; visual/publicação pendentes. Sem conversão ativa. |
| AUD-COUNTRY-06/07; AUD-STATS-01 / C17–19 | País e origem separados em negócios/fundiário; gravação cifrada, recuperação, filtros autorizados e agregados. Texto legado conservado. | QA demonstrada por formulário; visual e versão servida ativa não demonstradas. |
| AUD-GEO-02/03 / C17 | Fundiário aceita país→província→distrito→posto→localidade. 361 geometrias oficiais inequívocas importadas privadamente e recuperadas, sem duplicar na segunda execução. | QA: 9 províncias, 120 distritos, 232 postos. Ativo: zero geometrias. |
| AUD-SCAN-01 / C07 | ClamD real 1.5.4, assinaturas atualizadas, EICAR detetado e seis integrações reais passaram. | Serviço local disponível; arranque após reinício, manutenção e derivadas web pendentes. |
| AUD-STYLE-01 / C10 | Formato global passou; lint sem erros, 11 avisos existentes. | Critério concluído; não certifica interface. |
| AUD-UI-01 / C20 | Ícone de pesquisa ligado à rota existente de oportunidades. | Código preparado/rota ensaiada; clique visual pendente. |
O próximo lote prioriza **percursos existentes de guardar/recuperar, filtros, seletores, mapas e ações por perfil**. Rascunhos e novas jornadas educativas ficam depois destas correções, sem desaparecer do backlog.
## Contagens reconciliadas
A [matriz existente](matriz-requisitos.csv) contém **3.354 requisitos canónicos e 3.354 linhas de dados**, mais cabeçalho. Preserva **5.830 linhas de origem**, com IDs/aliases, fontes, trechos, hashes, versões divergentes e critérios por operação. Não foi criada outra matriz.
| Estado | Requisitos | Linhas de origem |
| --- | ---: | ---: |
| Concluído e demonstrado | 5 | 5 |
| Parcial | 3.198 | 5.380 |
| Não implementado | 146 | 440 |
| Implementado mas não ativado | 1 | 1 |
| Com falha no critério atualmente registado | 0 | 0 |
| Dependente de decisão concreta | 4 | 4 |
| Total | 3.354 | 5.830 |
Zero linhas no estado «com falha» **não significa zero falhas no portal**: requisitos com componentes corrigidos e componentes ainda ausentes permanecem parciais. Continuam sem implementação o workflow completo, contratos especializados e rascunho educativo incompleto. Continuam não demonstrados todos os consumidores/mapas e a interface renderizada.
Concluídos apenas nos critérios estreitos: AUD-OPS-02 (guarda QA), AUD-OPS-03 (leitura/preservação), AUD-COUNTRY-05 (API ISO), AUD-GEO-04 (recuperação do catálogo administrativo) e AUD-STYLE-01 (checks de formato). Catálogo API não encerra formulário/mapa. Contagens não são percentagem de aceitação; decomposição semântica de cláusulas compostas permanece AUD-DOC-01. As cinco etapas de prova estão separadas por requisito: interface → API → gravação → recuperação → resultado apresentado.
## Países, origem e estatísticas por percurso
**Negócios:** CountrySelect e 249 países nas props → POST/PUT autorizados → country=PT/origem=ZA no payload cifrado existente → GET recupera os dois → lista filtrada e estatísticas de negócio submetido ZA=1/PT=0. Draft fica fora do agregado; outra conta recebe 403/lista vazia. ZZ recebe 422 sem nova versão. Texto histórico Portugal conserva-se no draft até escolha explícita de PT; submissão completa exige ISO conhecido.
**Fundiário:** CountrySelect país/origem → POST/PUT do caso → payload cifrado separado → GET recupera país/origem e caminho dos quatro níveis → solicitar apoio conserva origem na solicitação/CRM; gestor filtra país PT/origem ZA. Agregado de interesses conta o pedido uma vez. Texto legado Moçambique permanece exato; inválido conserva versão; outra conta 404/403.
**Percursos anteriores preservados:** manifestação pública, quatro tipos de apoio, interesse em negócio, jornada e Balcão têm provas específicas de origem; simulador guarda países em snapshots cifrados, sem gerar cálculo por isso. Os conjuntos interests, desk e businesses são apresentados separadamente. São solicitações/negócios, não investidores únicos. Ausência permanece «não informado»: não foi inferida origem para os quatro interesses históricos ativos. [Cobertura por consumidor](cobertura-consumidores-lote2.md) identifica o que falta por formulário.
## Território, fontes e mapas
O inventário passa a **524 ficheiros e 60 anexos embebidos: 584 registos**, incluindo 11 originais novos de serviço/metadados/datasets GIS. Binários ClamAV e logs são artefactos de execução, não acervo documental. A aceitação das fontes oficiais mantém-se; metadados servem para identificar edição/âmbito, não recertificar credibilidade.
Fonte selecionada: serviço Mozambique/FeatureServer, origem **INE**, distribuição UNOCHA, edição **07/06/2019**, disponível no alojamento ArcGIS do Banco Mundial. Originais GeoJSON preservados por hash: ADM1=11, ADM2=159, ADM3=411. Importação exige origem, contagem integral, scan real do original, geometria válida/SRID 4326 e correspondência única de nome normalizado + pai. Códigos de fontes diferentes não foram equiparados automaticamente.
QA `desk_restore_20261009_171209_test:55441`: **9 + 120 + 232 = 361** correspondências importadas em `geo_geometries` existente; segundo import reutiliza todas e cria zero. Todas válidas e recuperáveis. **Lacunas: 2 províncias, 39 distritos, 179 postos sem correspondência inequívoca; nenhuma geometria de localidade nessa fonte.** As duas designações de Maputo diferem entre versões; sem remapeamento silencioso. Edição de 2019 não é declaração de atualidade jurídica.
Geometrias estão **internas, privadas, QA**. Não viram locais de investimento, polígonos publicados ou pontos inventados. Os 1.920 territórios recuperados em 597 pedidos API continuam prova de catálogo, não de campos/mapas. Mapas de oportunidades, catálogo/detalhe/portefólio, parcerias e zonas precisam de provas próprias de camada, filtro, geometria/identificador e resultado. Ativo mantém zero geometrias; 28 locais de projetos e 13 relações cluster–projeto foram preservados.
## QA, ações e limites
**379 testes passaram, 4.922 asserções, zero saltados; 156 testes frontend/reconciliação passaram.** TypeScript, PHPStan, build e formato global passaram; build conserva aviso de tamanho de chunks, lint 11 avisos existentes. PortalAuditNextLotTest demonstra maturidade, negócios e fundiário com persistência, recuperação, isolamento, inválidos e conflitos. Seis testes de ClamD real passaram, sem substituto fictício.
Inventário estático de todas as páginas/componentes TSX: **363 ocorrências de botões e 270 seletores/mapas**. Cinco dependem de contexto de diálogo/menu e exigem confirmação por percurso; não são classificados como falha só por falta de handler direto. Binding estático e os 352 GET anteriores por quatro perfis não demonstram todos os cliques/transições/anexos. O navegador continua indisponível; não há capturas apresentadas como prova atual.
Base ativa consultada READ ONLY: 288 tabelas; seis oportunidades reais IDs 1–6, 1.990 territórios, zero geometrias, dois negócios/duas revisões, quatro interesses sem origem, um dossier Balcão/zero pedidos. Cadastros vazios educativos/CRM/Bolsa não foram preenchidos artificialmente. Dos 209 hashes temporais comparáveis, 207 coincidem; cache/sessions diferem sem causa atribuída. Backup/restauro atual compara todas as 288 tabelas e cinco ficheiros.
## Instalação e próximo lote
Recursos continuam **installed=false; ready=true** no preview READ ONLY de 17:24:56 UTC. Backup/restauro verificado às **17:21:00 UTC**, QA `desk_restore_20261009_172050_test:55441`; reversão compatível nas 288 tabelas. Fingerprint `bb413e306779656699072f91235856bec626c1c6571ff2267a3d64417c7576ce`; validade até 10/10 17:21 UTC, sujeita às guardas.
Países/origem/estatísticas/maturidade do draft não exigem migration nem ClamD. Extensão privada de imagens/documentos/multilocalização exige a ação autenticada existente e aplica só `2026_10_09_030000_extend_opportunity_resources`, uma vez. Não repetir Balcão/Bolsa/gestão básica. ClamD limita scans/libertação dos binários afetados; GD/WebP do PHP web e scans de derivadas continuam prova separada. Serviço ClamD atual não comprova arranque após reinício.
Próximo lote: fechar API/persistência dos restantes seletores/filtros e ações existentes por consumidor/perfil; integrar em QA as camadas privadas já correspondidas e demonstrar resultados; completar workflow e consumidores da maturidade versionada sem reinterpretar histórico. Verificação visual retoma assim que houver navegador. Instalação não transforma preparação em aceitação integral.
Decisões humanas mantidas: pares oportunidade–projeto/cluster por ID/papel/citação; entidade operadora/contactos/termos; contactos/links/responsável por serviço; pesos/limiares/baseline dos pilotos. Nenhuma reabertura da aceitação oficial.
[Backlog](backlog.md) · [Matriz](matriz-requisitos.csv) · [Casos C01–C20](casos-reproducao.md) · [Cobertura e evidências](cobertura-consumidores-lote2.md) · [Plano de ativação](plano-ativacao.md) · [Inventário](inventario-fontes.csv). Dumps, ZIP, configuração, chaves e dados pessoais não acompanham os anexos.
'''
backlog = '''# InvesteMoz — backlog priorizado do lote 2
09/10/2026. Mesma [matriz](matriz-requisitos.csv): **3.354 requisitos, 5.830 linhas de origem**. Estados: 5 concluídos, 3.198 parciais, 146 não implementados, 1 implementado não ativo, 0 com falha no critério registado, 4 decisões concretas. Parcial pode conter funcionalidade ainda em falta. Código preparado ≠ QA demonstrada ≠ funcionalidade ativa.
## P0 — guardar, recuperar e preservar
**AUD-OPS-02/03 — concluídos no critério operacional.** Guarda host/porta/base e lock antes da limpeza; ensaios só em QA; consulta ativa READ ONLY. Aceitação cumprida: runner concorrente recusado, suite sequencial passa, snapshots preservados. Backup/restauro atual compara 288 tabelas/cinco ficheiros; 207/209 hashes temporais coincidem, divergência cache/sessions não atribuída.
**AUD-GEO-02 / C17 — falha fundiária corrigida em QA, requisito global parcial.** Remover condição errada province.parent_id=null; reutilizar geo_locations/InvestmentGeography, mantendo validação de descendentes e classificação. Aceitação QA: país→província→distrito→posto→localidade guarda/recupera e apresenta caminho nas props; IDs inválidos/outra conta negados sem alterar versão. Falta UI. Sem migration/ClamD.
**AUD-COUNTRY-07 / C18 — perda da origem corrigida em QA.** Conservar origem explícita no payload/hash/metadata ao solicitar apoio; reutilizar InterestSubmission e CRM interno. Aceitação QA: country PT/origem ZA continuam distintos no caso, recibo, pedido e filtro; uma contagem, replay sem duplicação, sem inferência histórica. Falta clique/resultado visual.
Toda nova falha de escrita/recuperação nos percursos seguintes sobe a P0, com reprodução, esperado/observado, causa e prova de conservação. Não instalar recursos ativos para diagnosticar.
## P1 — lote já corrigido, ainda sem aceitação visual
**AUD-OP-05 / C15 — 422 para 7/8 resolvido.** OpportunityMaturity/OpportunityManagement e seletor reutilizam management_draft. Oito códigos spec-v2 coexistem com seis valores legacy-v1. Aceitação demonstrada: oito criações/GET, 7/8=201, etapa/posição/versão recuperadas, código/posição incompatíveis 422, conflito 409, perfil indevido 403, replay único. Mudança só de versão sem etapa é recusada; legado não é reinterpretado. Próximo: filtros/fichas e publicação conscientes da versão, após workflow; não expor draft privado no catálogo. Sem migration/ClamD.
**AUD-COUNTRY-06 / C19 — negócios.** CountryCatalogue/CountrySelect + BusinessFormSchema/ExistingBusinessIntake/CanonicalBusinessRepository existentes. País/origem separados, ISO desconhecido 422, texto Portugal preservado no draft até escolha explícita, payload cifrado, cinco revisões conservadas. Filtros operam depois do escopo autorizado; drafts não entram no agregado. Falta visual e versão web ativa. Dependência: catálogo 249 existente, sem dados novos/tabela.
**AUD-COUNTRY-07 / C17–19 — fundiário.** País/origem separados; GET recupera nomes/códigos/caminho; submissão integra interesses/CRM uma vez; inválido conserva versão e legado exato. Falta visual. Sem ClamD ou extensão de recursos.
**AUD-STATS-01 — filtros/agregados.** DeclaredOriginStatistics mantém interests, desk e businesses separados; negócio só submetido, fundiário contabilizado como interesse. Aceitação QA: filtro ZA contém pedido, PT não; unknown permanece não informado; país não substitui origem; outra conta negada. Próximo: URL/seleção/nova sessão/tabela no navegador. Não contar investidores únicos.
**AUD-SCAN-01 / C07 — serviço real disponível.** ClamD 1.5.4 com bases oficiais, EICAR em memória detetado e seis integrações reais. Próximo: arranque após reinício, atualizações regulares e prova de GD/WebP web/scan de cada derivada. Critério: benigno/ameaça por hash, assinatura/data/versão, restrição só na operação afetada. Limite geral de 20 MB mantido; ADM3 GIS teve scan CLI separado, não alargamento do limite do portal.
**AUD-STYLE-01 / C10 — concluído.** Pint e formato global passaram; lint 0 erros/11 avisos. **AUD-UI-01 / C20 — pesquisa ligada à rota existente**, ainda precisa de clique/feedback no browser.
## P1 — próximo lote executável, por ordem
1. **AUD-UI-01; AUD-DASH-01; AUD-DESK-01/02; AUD-CRM-01; AUD-BIZ-01; AUD-LAND-01.** Percorrer ações existentes antes de novas jornadas: criar/editar/guardar/recuperar/pesquisar/filtrar, transições, exclusão lógica/restauro e anexos aplicáveis, por dono/revisor/gestor/consumidor. Reutilizar controllers/services/formulários existentes e inventário de 363 botões. Aceitação por ação: resposta/erro visível, versão/evento, GET seguinte e isolamento; GET de rota não fecha botão. API e persistência avançam sem browser; visual continua pendente. ClamD só nos anexos/scans afetados; recursos pendentes só nos percursos que usam a extensão.
2. **AUD-COUNTRY-01–04/06–07; AUD-STATS-01; AUD-SIM-01.** Fechar consumidores restantes por formulário, incluindo campos condicionais de serviços/Balcão e origem na recuperação. Reutilizar catálogo ISO/componentes/payloads; não inferir nacionalidade/residência/origem entre si. Aceitação: seleção/pesquisa → pedido válido → valor cifrado/canónico → nova sessão → nome/código e filtros/agregado reconciliados; ZZ 422 sem escrita, legado exato, unknown/todos, contas isoladas. Não depende de ClamD.
3. **AUD-GEO-01–03; AUD-FIELD-* — todos os seletores.** Inventário de 270 seletores/mapas é evidência de consumidores, não cobertura funcional. Reutilizar TerritoryFields/ProvinceSelect/InvestmentGeography e os 1.920 IDs existentes. Aceitação individual: pai limpa filhos, pesquisa paginada sem omissões, ID válido guarda/recupera, privado/descendente errado 422 conserva versão, nomes e caminho apresentados. Múltiplos locais de oportunidades dependem da extensão instalada em QA, não de repetir módulos.
4. **AUD-GEO-03 — camadas e lacunas GIS.** Reutilizar geo_geometries e importador guardado. Já há 361 correspondências internas em QA, scan original real, SRID/validade e replay zero novos. Próximo: conferir camadas em cada mapa, filtro/ID/geometria/legenda/resultado e política existente de acesso. Lacunas concretas: 2/39/179 sem correspondência por nível, nenhuma localidade; Maputo exige reconciliação explícita de versão/designação. Não usar centroides administrativos como investimento. Aceitação: fonte/edição/hash, correspondência inequívoca e resultado da camada; sem publicação ou vigência presumida. Procura de outras geometrias oficiais não reabre aceitação da fonte identificada.
5. **AUD-OP-03/04/05 — workflow e contratos especializados.** Reutilizar draft/versionamento/audit_events/categorias existentes. Implementar revisão→devolução→aprovação→publicação com perfis distintos e critérios por categoria; levar catálogo versionado até filtros/ficha pública sem vazar propostas. Aceitação: cada transição autorizada/negada, motivo/ator/versão, recuperação, publicação só do conteúdo aprovado; campos/regras por categoria, legado conservado. Pessoas reais necessárias para atos ativos, não para desenvolver/testar QA.
Depois de cada incremento, atualizar a mesma linha canónica, referências/versões, caso e cinco etapas de prova. Não esperar por decisões independentes nem criar tabelas/cadastros paralelos.
## P1/P2 — restantes pedidos preservados
**AUD-EDU-02/03/01:** rascunho incompleto de procura/capacidade e jornadas/painéis por ator continuam ausentes/incompletos. Curso/proposta em draft não os substitui. Entram depois dos percursos existentes acima. Reutilizar LabourDemand/TrainingCapacity/schemas, sem datas/zeros fictícios. Aceitação: draft privado incompleto guarda/recupera, submissão incompleta 422 conserva draft, versão/conflito/isolamento, exclusão dos agregados; completo segue revisão por ator distinto.
**AUD-LIB-01/02:** inventário 584 registos, disponibilidade/jurídico/cálculo independentes; preview/hash/dedup por bytes/conflito de identidade/scan/escrita privada/replay, nunca publicação automática. Original e autorização por ficheiro; associação a artigo/módulo não condiciona cadastro/consulta. Fonte fiscal ausente/parâmetro ambíguo indeterminado, nunca zero/taxa recente.
**AUD-SIM-02; AUD-PART-01; AUD-GUIDE-01:** regras/versionamento/cálculos explicáveis; candidatura/sala/marcos/retirada por papel; orientação com fonte/âmbito/período e recuperação. Preservar cadastros vazios sem fabricar população. Critério individual na matriz, não fecho por existência de menu.
**AUD-DOC-01:** separar semântica das cláusulas compostas preservando fonte/ID/versões; histórico não substitui estado atual. Original upgrade v4 e relatório outputs indicado não localizados; mensagem preservada como fonte sem hash inventado.
## Decisões humanas — perguntas exatas
- **AUD-OP-02:** quais pares de IDs oportunidade–projeto/cluster, papel e citação devem ser associados?
- **AUD-HUMAN-01:** qual entidade operadora, contactos e versões de termos/política estão autorizados para divulgação?
- **AUD-HUMAN-02:** quais contactos/links específicos e responsável real devem constar por serviço?
- **AUD-HUMAN-03:** que pesos, limiares, baseline/período e responsáveis devem ser usados nos pilotos?
Nenhuma pergunta é uma segunda validação da credibilidade oficial já aceite.
## Ativação e prova de fecho
379 testes/4.922 asserções/zero skips; 156 frontend/reconciliação; checks técnicos passaram. [Casos C01–C20](casos-reproducao.md), [cobertura por percurso](cobertura-consumidores-lote2.md), [plano autenticado](plano-ativacao.md). Browser indisponível; nenhuma demonstração visual atual.
Backup/restauro 09/10 17:21 UTC, 288 tabelas/cinco ficheiros, hash bb413e30…; ready=true, installed=false. Países/origem/estatísticas/maturidade privada não exigem migration; recursos privados exigem só extensão pendente autenticada; geometria QA é independente e privada. Não repetir Balcão/Bolsa/gestão básica. Instalação não fecha workflow/mapas/visual nem ativa cálculo fiscal.
'''
plan = '''# Plano de ativação autenticada — lote 2
09/10/2026. Preview READ ONLY 17:24:56 UTC: **installed=false, ready=true**. Preparação não é instalação ou conclusão funcional. Nenhum ato ativo executado nesta auditoria.
## Ordem e dependências reconciliadas
1. **Código/assets, sem migration:** maturidade versionada no draft, países/origem de negócios/fundiário, filtros/estatísticas, hierarquia fundiária e pesquisa. Reutilizam JSON/payloads cifrados/catálogos existentes; não convertem valores históricos. Verificar versão web/manifesto e percursos QA. ClamD e recursos não são dependências deste grupo.
2. **Preview com conta autorizada existente:** `/management/opportunity-resources-install`; destino `investemoz:5432`. Backup/restauro verificado em **09/10/2026 17:21:00 UTC**, válido até **10/10/2026 17:21:00 UTC** sujeito a código/destino/guardas. QA de compatibilidade `desk_restore_20261009_172050_test:55441`, 288 tabelas/cinco ficheiros; up/down preservou baseline. Fingerprint **bb413e306779656699072f91235856bec626c1c6571ff2267a3d64417c7576ce**. Mudança/expiração exige renovar provas pertinentes; não modificar prova para simular aceitação.
3. **Só extensão pendente, uma vez:** ação autenticada aplica `2026_10_09_030000_extend_opportunity_resources`. Imagens/documentos/multilocalização privados ficam disponíveis; não publica, não atribui relação/classificação e não ativa cálculo. Confirmar por leitura migration/evento/autor/hash e conservação dos IDs 1–6, relações 28/13, ficheiros/histórico. Não repetir Balcão/Bolsa/gestão básica: cada um tem um evento de instalação.
4. **Binários/derivadas afetados:** ClamD real 1.5.4 está disponível nesta sessão e integrações QA passaram. Arranque após reinício/atualização periódica, GD/WebP no PHP web e scan de cada derivada são provas específicas ainda pendentes. Não impedir metadados/países/origem/pesquisas por esta dependência; manter restrição concreta nos binários não verificados.
5. **Geometria, independente:** QA `desk_restore_20261009_171209_test:55441` contém 361 geometrias internas de 2019, originals/hash/scan e correspondências inequívocas; replay zero novos. Esta cópia não é a cópia de compatibilidade de recursos. Não copiar fixtures, publicar camadas ou declarar atualidade jurídica por importar. Ativo continua zero; reconciliar camadas/consumidores/lacunas antes do ato autenticado de uso ativo pertinente.
6. **Conteúdo/workflow real:** publicação/aprovação/contratos especializados e designações institucionais não surgem da extensão. QA avança sem pessoas inventadas; atos ativos usam contas/designações reais. Revisão visual retoma assim que o browser existir, sem declarar frontend observado agora.
QA global: 379 testes, 4.922 asserções, zero skips; 156 frontend/reconciliação; TypeScript/PHPStan/build/formato passaram. Escopo é preparação técnica/API/persistência, não aceitação integral do portal.
Reversão direta demonstrada **antes de novas escritas**. Depois de uso, preservar novos dados/eventos e reconciliar antes de down/restauro. Dumps, ZIP, .env/chaves permanecem privados. Provas: backup-proof, compatibility, activation-proof e resources-lote2-preview; não contornar autenticação ou impersonar conta ativa via CLI.
'''
coverage = '''# Evidências por consumidor — lote 2
09/10/2026. Inventário de evidências ligado aos IDs da matriz existente; **não é outra matriz de requisitos**. “Props” é resultado de GET/Inertia, não observação visual. Todos os ensaios com escrita são QA; ativo apenas leitura.
| Consumidor / requisito | Interface preparada | API → gravação → recuperação → resultado | Lacuna |
| --- | --- | --- | --- |
| Manifestação pública / COUNTRY-01–04 | CountrySelect país/origem | InterestOriginTest/PortalAuditContinuationTest: PT/ZA separados, metadata persistido, GET gestor/estatística, inválido sem escrita/replay único | Browser, restantes variações por consumidor |
| Apoio: quatro tipos / COUNTRY-04 | Campo país pertinente e origem opcional | PortalAuditContinuationTest: guarda ambos nos quatro tipos, recupera detalhe/origem, another actor denied | Browser/serviços condicionais restantes |
| Interesse em negócio público / COUNTRY-04 | Dois campos distintos | Provas anteriores de InterestSubmission/recuperação; não confundir com wizard privado | Visual e ensaio por cada variação |
| Jornada / COUNTRY-04 | Seleção e props country/origin | InvestmentPortfolioTest conserva recuperação; pedidos integram interesses | Visual/nova sessão renderizada |
| Wizard de negócios / COUNTRY-06 | CountrySelect país/origem, 249 países | PortalAuditNextLotTest: POST/PUT encrypted payload → GET → filtros country/origin; draft aggregate 0, submitted ZA=1/PT=0; legado Portugal, ZZ 422 preserva versão, other actor 403/list empty | Visual/perfis adicionais/revisão completa |
| Assistência fundiária / COUNTRY-07; GEO-02 | País/origem e quatro níveis | Mesmo teste: POST/PUT/GET cifra e recupera nomes/territoryPaths; request-support preserva ZA; gestor filtra PT/ZA, agregado interests uma vez; legado e versão conservados | Visual/mapas/anexos/transições restantes |
| Balcão / DESK-01; COUNTRY-04; GEO-02 | Origem e TerritoryFields | VirtualDeskTest/PortalAuditContinuationTest: payload cifrado, localidade/path recuperados; origem agregada desk separada | Todos os campos condicionais por serviço, transições/visual |
| Simulador / SIM-01; COUNTRY-05 | País ISO/fundos e território separados | SimulationPrivateDraftTest/Continuation: PT/ZA cifrados GET, legado, ZZ 422/other actor 404; nenhum cálculo por guardar | Demais campos/cálculos/visual |
| Gestor/CRM / STATS-01 | Filtros country/origin/unknown e 3 agregados | GET authorized scope/filtered rows/counts; interests/desk/businesses separados, business drafts excluídos | URL/seleção/tabela no navegador; escala/performance das listas cifradas |
| Draft de oportunidade / OP-05 | Catálogo server-side 8; opção histórica | NextLotTest: 8 POST/GET, 7/8=201, canonical code/position/version stored private JSON; legacy raw unchanged; mismatch/version-only 422, conflict409/actor403 | Publicação/filtros públicos versionados/visual |
## Território por consumidor
Catálogo: 597 pedidos/1920 IDs na cópia ativa restaurada; não se generaliza aos campos. Fundiário e Balcão têm prova própria de hierarquia/persistência; demais controles mantêm prova individual pendente.
- Seletores de submissão/perfil/oportunidades, negócios, parceria, simuladores e administração: conferência de tipo/pai/paginação/seleção/limpeza de filhos/recuperação/erro/visual por componente. Reutilizar IDs existentes, sem transformar cadastro em preenchimento automático.
- Mapas do catálogo/detalhe/portefólio: `/api/v1/investment/map`; mapas de zonas: `/api/v2/investment/zone-map`; mapas de parcerias e respectivas áreas/IDs têm critérios próprios. Campos cartográficos não fecham por responder a API territorial.
- Geometrias administrativas INE/UNOCHA 2019: originais 11/159/411, privadas QA 9/120/232. Correspondência única nome+pai; nenhum centro administrativo vira ponto de oportunidade. Sem locality geometry; unmatched 2/39/179. Maputo diverge por designação/versão.
## Ações e perfil
consumer-actions-lote2.json inventaria todas as páginas/componentes: 363 botões e 270 seletores/mapas. Cinco bindings requerem contexto (menu/avatar/diálogo de exclusão/passkey/cancelamento). Não se infere falha ou sucesso só pelo AST. C20 encontrou pesquisa sem ação e liga-a à rota existente.
Ensaios já presentes demonstram negativa entre contas e gravação/recuperação dos percursos específicos; não se afirma cobertura de cada botão. Próximo lote executa dono/revisor/gestor/público, com retorno visível e evento/versão quando aplicável. No browser indisponível, API/persistência continuam; visual fica separado.
## Manifesto das provas exportáveis
- phpunit-final.json; phpunit-lote2-final.xml: 379 pass, 4922 assertions, zero skipped.
- consumer-actions-lote2.json: inventário estático, não DOM observado.
- geometry-qa-adm1/2/3-import.json: destino QA, counts/reuse/SRID/validity/hash; geometry-source-scans.json: scans reais dos originais.
- resources-lote2-preview.json; activation-evidence.json: destino ativo somente leitura, hash/provas, ready=true/installed=false.
- clamd-lote2.json: saúde/versão/assinatura/EICAR e hashes; sem afirmar scans de derivadas não ensaiadas.
- contagens-requisitos.json: 3354 canónicos/5830 origens conservadas; matriz CSV mantém aliases/versões.
Logs de execução e snapshots pessoais/dumps/configuração permanecem privados. Provas de geometria e compatibilidade usam cópias QA distintas; não misturar seus estados.
'''
activation = json.loads((proof / 'activation-evidence.json').read_text(encoding='utf-8'))
preview = json.loads((proof / 'resources-lote2-preview.json').read_text(encoding='utf-16').lstrip('\ufeff'))
backup_time = activation['verified_at'][11:19]
backup_short = backup_time[:5]
compatibility = json.loads((proof.parent / 'opportunity-resources-compatibility.json').read_text(encoding='utf-8'))
for name, text in [('relatorio-executivo.md', report), ('backlog.md', backlog), ('plano-ativacao.md', plan)]:
text = text.replace('bb413e306779656699072f91235856bec626c1c6571ff2267a3d64417c7576ce', activation['code_hash'])
text = text.replace('bb413e30…', activation['code_hash'][:8] + '…')
text = text.replace('17:21:00', backup_time).replace('17:21', backup_short)
text = text.replace('17:24:56', preview['captured_at'][11:19])
text = text.replace('desk_restore_20261009_172050_test', compatibility['target']['database'])
file = docs / name
previous = file.read_text(encoding='utf-8')
marker = '## Histórico da continuação anterior — não representa o estado atual'
if marker in previous:
previous = previous.split(marker, 1)[1].lstrip()
file.write_text(text + '\n' + marker + '\n\n' + previous, encoding='utf-8')
(docs / 'cobertura-consumidores-lote2.md').write_text(coverage, encoding='utf-8')
cases = docs / 'casos-reproducao.md'
append = '''
## Atualização C07/C10/C15 — lote 2, observações antigas preservadas
C07: indisponibilidade corrigida; ClamD real 1.5.4/assinaturas, EICAR detetado em memória e seis testes reais passaram. Restam arranque após reinício/atualizações e GD web/derivadas. C10: formato global corrigido e checks passaram; lint 11 avisos existentes. C15: POST maturity_level=7/8 agora 201 em QA, GET recupera versão/etapa/posição. Oito etapas spec-v2 explícitas, seis legacy-v1 preservadas. Código/posição incoerentes ou versão sem etapa 422; conflito409/perfil403/replay único. AUD-OP-05 parcial por workflow/publicação/visual, não pela rejeição antiga. PortalAuditNextLotTest/phpunit-lote2-final.xml. Nenhuma escrita ativa.
## C17 — província com país pai recusada no fundiário — P0/P1
Reprodução: criar caso privado QA, escolher os IDs válidos país→província→distrito→posto→localidade do cadastro. Esperado: guardar e recuperar hierarquia pública válida. Observado antes: 422 province_id apesar de cadeia correta. Causa identificada: StoreLandAssistanceRequest exigia parent_id=null para província, enquanto o catálogo tem país pai. Correção remove essa suposição; conserva tipo/classificação/descendência/ciclos. QA NextLotTest POST/PUT/GET recupera quatro níveis e territoryPaths; inválido/outra conta recusados, versão preservada. Interface preparada, visual pendente. Ativo não migrado/reescrito.
## C18 — origem fundiária omitida ao pedir apoio — P0/P1
Reprodução: caso QA com country PT e declared_origin_country_code ZA; executar request-support e GET gestor/filtrar origem. Esperado: ZA continua origem, PT país. Observado por código anterior: campo não constava do payload enviado a InterestSubmission, perdendo rastreabilidade. Correção inclui origem no payload/hash/metadata existentes. QA conserva ZA no pedido/CRM/recuperação, filtro PT/ZA e agregado interests uma vez; conta indevida 404/403. Não inferir valores históricos. Visual pendente.
## C19 — negócios/fundiário sem catálogo completo e percurso de origem — P1
Reprodução por código/API: wizard country texto livre, sem origem separada/filtros/agregado de negócios; fundiário sem seleção ISO. Esperado: países pertinentes selecionáveis, legado conservado, origem explícita independente e recuperável. Correção CountryCatalogue/CountrySelect/validação e payloads cifrados existentes. QA negócios: draft PT/ZA, ZZ422 conserva versão, texto Portugal recuperado exato, escolha explícita PT, submissão válida/agregado ZA1, filtros e outro ator negado; cinco revisões. QA fundiário: PT/ZA/legado Moçambique recuperados, apoio preserva origem. Não reivindicar visual ou cobertura dos outros formulários por estas provas.
## C20 — botão de pesquisa do cabeçalho sem efeito — P1
Reprodução por inspeção: app-header.tsx apresentava botão Search sem href/onClick ou formulário/contexto de ação. Esperado: abrir pesquisa existente com destino visível. Causa: ícone decorativo embrulhado em Button sem binding. Correção usa Link /oportunidades via asChild, com nome acessível. Rota/compilação verificadas; clique/URL/feedback visual ainda pendentes por browser indisponível. Não é ação de persistência. Inventário dos demais 363 botões não é aceitação funcional.
'''
if '## Atualização C07/C10/C15 — lote 2' not in cases.read_text(encoding='utf-8'):
cases.write_text(cases.read_text(encoding='utf-8') + append, encoding='utf-8')
notice = '''
## Estado de auditoria — lote 2, 09/10/2026
Prevalece o [relatório atualizado](auditoria-portal/relatorio-executivo.md) sobre estados históricos: maturidade 7/8 já grava/recupera em QA com catálogo versionado, negócios/fundiário têm países/origem separados e provas por percurso, 361 geometrias oficiais internas estão em QA, ClamD real está disponível. Workflow/publicação, cobertura transversal/visual/mapas e recursos ativos continuam pendentes. 379 testes/4922 asserções/zero skips; recursos ready=true, installed=false. A [mesma matriz](auditoria-portal/matriz-requisitos.csv) conserva 3354 requisitos/5830 origens; próximo lote no [backlog](auditoria-portal/backlog.md) prioriza falhas de percursos existentes antes de novas jornadas educativas.
'''
for name in ['gestao-oportunidades-dashboard.md', 'backlog-mestre.md']:
file = docs.parent / name
if file.is_file() and '## Estado de auditoria — lote 2' not in file.read_text(encoding='utf-8'):
file.write_text(file.read_text(encoding='utf-8') + notice, encoding='utf-8')
print(json.dumps({'updated_existing_matrix_documents': True, 'parallel_matrix_created': False}, ensure_ascii=False))