From 13f68f1bd8676d5ed418876a562af259e3887ba8 Mon Sep 17 00:00:00 2001
From: nala
Date: Wed, 21 Oct 2026 08:43:12 +0200
Subject: [PATCH] fix: concluir recuperacao de exportacoes e consolidar
candidata QA
---
...-review-continuation-20261020-receipt.json | 163 +++++++++++-
.../unification/traceability-and-manual.md | 91 +++++++
.../v2/auditoria-portal/matriz-requisitos.csv | 16 +-
.../js/components/project-dossier-export.tsx | 233 ++++++++++--------
resources/js/lib/dossier-export-state.ts | 89 +++++++
resources/js/lib/project-dossier-document.ts | 7 +-
.../frontend/dossier-export-recovery.test.mjs | 141 +++++++++++
.../frontend/project-dossier-report.test.mjs | 9 +
8 files changed, 639 insertions(+), 110 deletions(-)
create mode 100644 resources/js/lib/dossier-export-state.ts
create mode 100644 tests/frontend/dossier-export-recovery.test.mjs
diff --git a/docs/investmoz/simulations/integrated-review-continuation-20261020-receipt.json b/docs/investmoz/simulations/integrated-review-continuation-20261020-receipt.json
index 54ebb083..d7305b5d 100644
--- a/docs/investmoz/simulations/integrated-review-continuation-20261020-receipt.json
+++ b/docs/investmoz/simulations/integrated-review-continuation-20261020-receipt.json
@@ -158,5 +158,166 @@
4
],
"remaining_scope": "Read-only remote collection; native PDF; new cashflow visual continuation; evidence closure; excludes waiting and tax-engine integration",
- "secrets_and_private_fixtures": "Not included in source manifest or Git"
+ "secrets_and_private_fixtures": "Not included in source manifest or Git",
+ "current_reconciliation_20261021": {
+ "items": {
+ "AUD-SIM-INT01": {
+ "status": "Concluído no recorte",
+ "remaining": "Nenhum delta de validação de data por demonstrar; prova anterior preservada."
+ },
+ "AUD-SIM-INT02": {
+ "status": "Parcial",
+ "remaining": "Leitura remota concluída: zero regras de todos os estados na homologação, tal como QA; seis referências jurídicas não são parâmetros executáveis. Falta cadastro fundamentado por componente/âmbito/período e ligação funcional ao motor fiscal. Fontes e análises existentes reutilizáveis; aceitação oficial da Tempo de08/10 preservada. Não activar taxas nem importar/publicar por esta reconciliação."
+ },
+ "AUD-SIM-INT03": {
+ "status": "Concluído no recorte",
+ "remaining": "A/B, logout/novo login, recuperação e recusa pela aplicação demonstrados anteriormente. A tesouraria tem prova API de nova sessão e prova visual de recuperação por recarga. Não atribuir ao navegador nova sessão dos valores de tesouraria, nem nova certificação RLS; limites expressos conservados."
+ },
+ "AUD-SIM-INT04": {
+ "status": "Concluído no recorte demonstrado",
+ "remaining": "Histórico24/12 visível, hashes preservados e versões temporais sintéticas do resolvedor conferidas. Execução fiscal integrada com parâmetros reais pertence ao saldo de02 e não foi demonstrada por estes testes."
+ },
+ "AUD-SIM-INT05": {
+ "status": "Concluído nos controlos delimitados",
+ "remaining": "Controlos independentes de caixa/plano/crédito, zero/desconhecido e moedas preservados. Não são validação de taxas legais nem certificação de toda a contabilidade."
+ },
+ "AUD-SIM-INT06": {
+ "status": "Concluído na apresentação e comparação deste relatório",
+ "remaining": "Rodapé do PDF nativo fechado em QA segundo provas apresentadas;10 páginas/valores/CSV não repetidos. Tempo declarou que não abriu imagem/PDF pelos caminhos locais: registar aceitação das provas, não revisão visual directa do utilizador. Outras provas de relatório conservadas; falhas interactivas de exportação/anexos mantêm saldo em07."
+ },
+ "AUD-SIM-INT07": {
+ "status": "Parcial",
+ "remaining": "Gravação503→nova tentativa→recuperação e exportações normais demonstradas. Faltam falhas dirigidas de geração Word/ZIP/PDF e retoma; teste interactivo de limite de anexo não ocorreu por bloqueio da ferramenta antes do envio. Nova leitura do código: três catch apresentam cause.message para Error, podendo mostrar texto técnico sem tradução. Sem nova falha de execução alegada."
+ },
+ "AUD-SIM-INT08": {
+ "status": "Parcial",
+ "remaining": "Inventário estático,404 real e traduções de validação preservados. Classificar/apresentar em português os erros dinâmicos das bibliotecas de exportação (cause.message, três consumidores) e conferir estados residuais/governação delimitados; não certificar todos os textos dinâmicos do catálogo."
+ }
+ },
+ "remaining_hours_delimited": [
+ 1,
+ 2
+ ],
+ "integral_fiscal_implementation_estimated": false,
+ "user_direct_visual_review_of_local_files": false,
+ "native_footer_accepted_on_presented_evidence": true,
+ "remote_rule_count": 0,
+ "remote_legal_reference_count": 6,
+ "supersedes_prior_pending": [
+ "remote authentication and inventory",
+ "native print save and visual footer correction",
+ "cashflow screen/download values"
+ ],
+ "tool_limits_retained": [
+ "interactive file chooser before attachment upload",
+ "native save performed by user"
+ ],
+ "branch": "codex/simulator-integrated-review",
+ "main_merge": false,
+ "read_only_evidence_sha256": "bbb2d2f0b001f1f439ce2bf8e60a4233467463f5cfa430dd05b82f515f5d9a5f"
+ },
+ "candidate_20261021": {
+ "branch": "codex/simulator-integrated-review",
+ "base": "c22003a3",
+ "main_integration": false,
+ "active_changes": false,
+ "new_tests": 4,
+ "typescript": "passed",
+ "browser": {
+ "word_failure_retry": "passed, 2 attempts / 1 success",
+ "pdf_failure_retry": "passed, failed popup closed / one populated retry",
+ "zip_failure_retry": "passed: failed ZIP, edited title/unchecked section and one attachment retained; retry produced one valid archive",
+ "attachment_limit_ui": "passed: refused16MB, prior valid entry retained",
+ "attachment_valid_retry": "passed: duplicate selection leaves one entry and translated status"
+ },
+ "duplicate_prevention": "synchronous gate test passed; attachment name+SHA256 identity test passed; ZIP single original test passed",
+ "logs": "local diagnostic console; no backend telemetry added",
+ "accepted_evidence_reused": [
+ "native PDF 10-page footer QA acceptance",
+ "financial values and CSV",
+ "A/B and new session",
+ "historical snapshots and temporal resolver",
+ "read-only remote fiscal inventory"
+ ],
+ "limitations": [
+ "Synthetic wrapper injects generator faults only and is excluded from deployment",
+ "Native print and values/CSV proofs reused, not repeated",
+ "Transient attachment read/concurrent-click proofs are automated; manual chooser path observed separately",
+ "Local console diagnostics are not persistent server audit",
+ "Fiscal integration remains incomplete; catalogue/governance language is not globally certified"
+ ],
+ "sources": [
+ {
+ "path": "resources/js/components/project-dossier-export.tsx",
+ "sha256": "c0bbea29c8e307785cbe54014a85d6271c723a541bea9f2ad5196118b9570764"
+ },
+ {
+ "path": "resources/js/lib/dossier-export-state.ts",
+ "sha256": "ac40e30134ba56b67c6c6a3b044aaeb110750cac53e0934794c8a7d346d745fe"
+ },
+ {
+ "path": "resources/js/lib/project-dossier-document.ts",
+ "sha256": "3bec7565324587bdd42f65f5b3c723597ec554b1c80376bfb45d350516eae16f"
+ },
+ {
+ "path": "tests/frontend/dossier-export-recovery.test.mjs",
+ "sha256": "b4112d612ce204c41b7376e64a0c15e7b85a6ec19087b0ed5415c1114d99f2b2"
+ },
+ {
+ "path": "tests/frontend/project-dossier-report.test.mjs",
+ "sha256": "77e33425e33e7ca0290e60e0b09fab7bbe5c8bd1eef196dd0863452da8f06271"
+ }
+ ],
+ "remaining_engineering_hours_delimited": [
+ 0,
+ 0
+ ],
+ "review_pending": true,
+ "build_manifest_sha256": "e4846e02db6112bce9c1f5466038e0a25f381c17fdcd8fe54248a7068a0645dd",
+ "evidence": [
+ {
+ "path": "outputs\\simulator-continuation-20261020\\export-word-error-20261021.txt",
+ "sha256": "b1c984663ea27bbeb5bfe760ab181314142f32cc9f6b27fa11c2fb7d7f0456ca"
+ },
+ {
+ "path": "outputs\\simulator-continuation-20261020\\export-pdf-error-20261021.txt",
+ "sha256": "b46f597e185874875d823d2c90219b555ee1f2028b5d144e00754db73468ed41"
+ },
+ {
+ "path": "outputs\\simulator-continuation-20261020\\export-pdf-retry-20261021.txt",
+ "sha256": "091679de9a60e4f22e2d0cb2127b736addfc9e2752fb0bb2aec051ddcb51f3c8"
+ },
+ {
+ "path": "outputs\\simulator-continuation-20261020\\export-zip-error-20261021.txt",
+ "sha256": "eda788b6f69b7fbcbb13aadf44dd0d3fbe695a2f050445b6f6a6d6553e7dc63d"
+ },
+ {
+ "path": "outputs\\simulator-continuation-20261020\\export-zip-retry-20261021.txt",
+ "sha256": "ef8c3c2197cb77260c1f8a1f169f282f1a14376e2aa331d26e9b98aee45e92c3"
+ },
+ {
+ "path": "outputs\\simulator-continuation-20261020\\attachment-limit-preserved-20261021.txt",
+ "sha256": "2132c4ddfaf044e8349766322514e9c6ce5c1a0f06236bfb4323b8a010e73197"
+ },
+ {
+ "path": "outputs\\simulator-continuation-20261020\\attachment-duplicate-retry-20261021.txt",
+ "sha256": "3027ea5949168df879442bb04a481d3f8c5e4741e470d30875e1dc6c25892312"
+ },
+ {
+ "path": "outputs\\simulator-continuation-20261020\\export-zip-content-proof-20261021.json",
+ "sha256": "6ee6bece4d2110c996bad2d686b24970c9d199eff2940dfba34e285f005f0f7c"
+ }
+ ],
+ "build_exit_code": 0,
+ "existing_items_current_scope": {
+ "AUD-SIM-INT01": "demonstrated within bounded scope; see existing manual for limits",
+ "AUD-SIM-INT02": "partial; fiscal implementation remains open",
+ "AUD-SIM-INT03": "demonstrated within bounded scope; see existing manual for limits",
+ "AUD-SIM-INT04": "demonstrated within bounded scope; see existing manual for limits",
+ "AUD-SIM-INT05": "demonstrated within bounded scope; see existing manual for limits",
+ "AUD-SIM-INT06": "demonstrated within bounded scope; see existing manual for limits",
+ "AUD-SIM-INT07": "demonstrated within bounded scope; see existing manual for limits",
+ "AUD-SIM-INT08": "demonstrated within bounded scope; see existing manual for limits"
+ }
+ }
}
diff --git a/docs/investmoz/unification/traceability-and-manual.md b/docs/investmoz/unification/traceability-and-manual.md
index efed4715..ce647e09 100644
--- a/docs/investmoz/unification/traceability-and-manual.md
+++ b/docs/investmoz/unification/traceability-and-manual.md
@@ -1623,3 +1623,94 @@ Artefactos em `outputs/simulator-continuation-20261020/`: `interface-comparison.
Provas adicionais: teste HTTP com dois dossiers, logout lógico/nova sessão, recuperação exacta e recusa por outra conta passou (8 asserções), em transacção revertida no clone. Quatro controlos frontend dirigidos passaram, incluindo recuperação de mês vazio, valor inválido para correcção, relatório sem zero inventado e pressupostos completos do crédito. As 10 verificações do exportador afectado passaram; teste temporal sintético passou (7 asserções); erro HTTP em português passou (3). TypeScript/build e sintaxe PHP passaram. A conferência visual do novo componente de tesouraria com sessão real QA permanece por executar depois de fechar a impressão do Edge; não foi substituída por uma prova unitária.
**Saldo revisto após esse achado: 2–4 h de verificação delimitada**, já descontado o desenvolvimento concluído: leitura remota 0,5–1 h; PDF nativo 0,5–1 h; continuidade visual/saída da tesouraria recém-corrigida 0,5–1 h; consolidação das provas e limitações 0,5–1 h. Exclui espera por autenticação/ficheiro e a integração funcional futura das regras fiscais. Esta estimativa substitui 1–3 h acima por uma divergência concreta; não retoma as 6–10 h nem as 18–30 h originais.
+
+
+### Retoma da conferência visual de tesouraria — 21/10/2026
+
+[Retoma 21/10/2026] QA 18576, clone simulator_review_delta_20261020_test: sessão sintética renovada por login normal; gravação autenticada e recarga recuperaram saldo 123, receita 900, custos 600, calendário mensal 10/vazio/0, crédito IVA estimado 500. Caixa conhecida 3713 MZN; total indeterminado desde mês 2; crédito estimado excluído da caixa. Prova visual cashflow-recovered-20261021.png e snapshot .txt em outputs/simulator-continuation-20261020. Não certifica recuperação destes novos valores após outro login, CSV/DOCX ou PDF nativo. Ligação de controlo do navegador perdida durante espera de download; não atribuir falha à aplicação. Leitura remota aguarda identificação da ligação SSH; zero alterações no destino.
+
+
+### Leitura fiscal remota e saída nativa — 21/10/2026
+
+[Leitura SSH 21/10/2026 08:17 Maputo] Zero regras em simulation_tax_rule_versions na homologação, incluindo todos os estados por leitura administrativa sem ocultação RLS. Seis referências em investment_legal_sources; não são parâmetros executáveis. QA também tinha zero regras. BEGIN READ ONLY/SELECT/ROLLBACK; zero escritas. Prova homologation-fiscal-readonly.json. O git HEAD registado é do checkout consultado, não certifica a revisão do build servido. A ausência de cadastro não é ausência de fontes oficiais nem reabre a aceitação da Tempo de 08/10. Não implementa a ligação funcional ao motor fiscal.
+
+[Exportação nativa 21/10/2026] Saída actual aberta pelo botão do portal: revisão 4, 12 meses, MZN, saldo inicial123/receita900/custos600, calendário10/vazio/0, caixa conhecida3713 e total indeterminado coincidem com o ecrã. Crédito estimado500 identificado como pressuposto, não somado à caixa. Prova portal-print-current-20261021.txt. Relatório de20/10/revisão2 preservado, sem o confundir com o actual. Downloads: sem novo CSV na pasta habitual ou nos temporários locais conferidos; isso não demonstra falha nem cancelamento. Histórico de downloads bloqueado pela política da ferramenta; caminho do ficheiro solicitado antes de repetir. PDF nativo aberto, mas paginação/legibilidade aguardam o ficheiro efectivamente guardado pelo Edge; conversão DOCX/PDF anterior não conta como essa prova. Perda da ligação e bloqueio de controlo durante impressão são limitações da ferramenta, sem falha do simulador demonstrada.
+
+
+### Ficheiros de Transferências recuperados — 21/10/2026
+
+[Fecho da verificação dos ficheiros 21/10/2026] Transferências Windows redireccionada para \\Mac\Home\Downloads; CSV concluído08:12:46, PDF nativo08:17:19. Sem repetir downloads. Os12 registos mensais do CSV coincidem exactamente com o snapshot do ecrã após correspondência de colunas; PDF revisão4 conserva valores mensais, MZN,12meses,123/900/600, crédito estimado500 não caixa e caixa conhecida3713. Os10 PNG do PDF nativo foram inspeccionados: defeito confirmado na linha repetida de rodapé, sobreposta ao corpo perto do topo de páginas, incluindo2,6e10. Conteúdo/valores conferidos; paginação/legibilidade não aceites até correcção e nova prova nativa. Não é conversão DOCX/PDF. Perda de ligação continua limitação da ferramenta e não causou falha do download; sobreposição é defeito distinto demonstrado no PDF. Provas: download-native-inspection-20261021.json, portal-cashflow-20261021.csv, portal-native-20261021.pdf e native-pdf-render/. A indicação anterior de ficheiros pendentes fica superada por esta prova. Sem alteração funcional nem escrita remota.
+
+
+### Correcção do rodapé do PDF nativo em QA — 21/10/2026
+
+[Correcção do rodapé nativo QA 21/10/2026] Origem: pedido expresso da Tempo nesta conversa; solução de implementação, sem regra organizacional nova. Causa em createProjectDossierPrintHtml (project-dossier-document.ts): footer position:fixed/bottom:-14mm sobrepunha a área fragmentada de impressão. Substituído na impressão por caixas @page @bottom-left/@bottom-right, dentro da margem inferior reservada20mm, com identificação/revisão e número de página/total. Rodapé normal de ecrã conservado; sem diminuir letras do corpo (10,5pt), tabelas, cabeçalhos ou origens (9pt), nem retirar conteúdo. Mesmo dossier B/revisão4 regenerado pelo botão do portal QA18576 e guardado no Edge, não por conversão DOCX. 10→10 páginas A4; comparação automática do corpo por página, descontando apenas hora de emissão/rodapé/contador, coincide integralmente. Inspecção visual dos10 PNG: sem sobreposição, cabeçalhos de tabela repetidos, quebras/linhas preservadas, última página íntegra e numeração1/10→10/10. Rodapés medidos inteiramente na margem inferior. Ecrã QA conferido após build; estilos screen e geradores DOCX/ZIP inalterados por comparação de fontes. 10 testes do exportador, TypeScript e build passaram; escape da revisão na nova string CSS verificado. Reutilizadas provas de valores e CSV aceites; não repetido download/aritmética. Provas: native-footer-fix-20261021.json; portal-native-fixed-20261021.pdf; native-footer-before-after-20261021.jpg; native-pdf-fixed-render/; screen-after-print-fix-20261021.png. Fechado exclusivamente o defeito de rodapé neste relatório QA; limitações e restantes critérios de AUD-SIM-INT06 mantêm âmbito próprio. Relato anterior de sobreposição fica superado neste delta pela comparação antes/depois. Branch codex/simulator-integrated-review separada de main, sem integração, escrita remota ou disponibilização activa; revisão prevista mantém-se pendente.
+
+
+### Saldo consolidado dos oito itens — 21/10/2026
+
+Reconciliação a pedido expresso da Tempo. O fecho do rodapé limita-se à apresentação deste relatório e baseia-se nas provas apresentadas; o utilizador declarou não ter conferido a imagem nem o PDF pelos caminhos locais. Não é fecho da revisão integral do simulador. Reutilizadas as provas aceites, sem repetir10 páginas, valores,CSV ou consulta SSH.
+
+| Item existente | Estado no recorte | Saldo / limite |
+|---|---|---|
+| AUD-SIM-INT01 | Concluído no recorte | Nenhum delta de validação de data por demonstrar; prova anterior preservada. |
+| AUD-SIM-INT02 | Parcial | Leitura remota concluída: zero regras de todos os estados na homologação, tal como QA; seis referências jurídicas não são parâmetros executáveis. Falta cadastro fundamentado por componente/âmbito/período e ligação funcional ao motor fiscal. Fontes e análises existentes reutilizáveis; aceitação oficial da Tempo de08/10 preservada. Não activar taxas nem importar/publicar por esta reconciliação. |
+| AUD-SIM-INT03 | Concluído no recorte | A/B, logout/novo login, recuperação e recusa pela aplicação demonstrados anteriormente. A tesouraria tem prova API de nova sessão e prova visual de recuperação por recarga. Não atribuir ao navegador nova sessão dos valores de tesouraria, nem nova certificação RLS; limites expressos conservados. |
+| AUD-SIM-INT04 | Concluído no recorte demonstrado | Histórico24/12 visível, hashes preservados e versões temporais sintéticas do resolvedor conferidas. Execução fiscal integrada com parâmetros reais pertence ao saldo de02 e não foi demonstrada por estes testes. |
+| AUD-SIM-INT05 | Concluído nos controlos delimitados | Controlos independentes de caixa/plano/crédito, zero/desconhecido e moedas preservados. Não são validação de taxas legais nem certificação de toda a contabilidade. |
+| AUD-SIM-INT06 | Concluído na apresentação e comparação deste relatório | Rodapé do PDF nativo fechado em QA segundo provas apresentadas;10 páginas/valores/CSV não repetidos. Tempo declarou que não abriu imagem/PDF pelos caminhos locais: registar aceitação das provas, não revisão visual directa do utilizador. Outras provas de relatório conservadas; falhas interactivas de exportação/anexos mantêm saldo em07. |
+| AUD-SIM-INT07 | Parcial | Gravação503→nova tentativa→recuperação e exportações normais demonstradas. Faltam falhas dirigidas de geração Word/ZIP/PDF e retoma; teste interactivo de limite de anexo não ocorreu por bloqueio da ferramenta antes do envio. Nova leitura do código: três catch apresentam cause.message para Error, podendo mostrar texto técnico sem tradução. Sem nova falha de execução alegada. |
+| AUD-SIM-INT08 | Parcial | Inventário estático,404 real e traduções de validação preservados. Classificar/apresentar em português os erros dinâmicos das bibliotecas de exportação (cause.message, três consumidores) e conferir estados residuais/governação delimitados; não certificar todos os textos dinâmicos do catálogo. |
+
+**Estimativa restante deste recorte:1–2h de engenharia**, excluindo espera por interacção necessária da ferramenta: 07/08 agrupados0,75–1,5h para tratamento e conferência dirigida de erros dinâmicos/retoma/anexos; 0,25–0,5h para reconciliação final das provas. Não somar o mesmo erro duas vezes por aparecer em07e08. Substitui o saldo anterior2–4h porque leitura remota, apresentação nativa e comparação da tesouraria já foram executadas. Não inclui cadastrar/aplicar regras fiscais reais, integrar fórmulas no motor ou certificar todo o catálogo. O esforço para02 integral permanece por dimensionar por componente, âmbito, período e correspondência documental; não há estimativa de conclusão integral obtida apenas deste1–2h.
+
+Próxima execução delimitada: corrigir a apresentação de excepções brutas nos três exportadores, conferir falha/retoma e os limites interactivos que faltam, preservando os relatórios/CSV já aceites. Branch codex/simulator-integrated-review mantida separada de main até à revisão consolidada. Nenhuma nova concessão, regra fiscal, migration ou escrita remota.
+
+
+### Candidata consolidada da revisão do simulador — 21/10/2026
+
+Origem: pedido expresso da Tempo para fechar apenas falhas dirigidas de exportação/anexos, apresentação das mensagens e consolidação. As 1–2 h anteriores respeitavam a esse recorte, não à implementação fiscal integral. A branch `codex/simulator-integrated-review` permanece separada de `main`; não integrar antes da revisão consolidada porque a cadeia existente disponibiliza automaticamente a revisão integrada.
+
+**Separação funcional preservada.** Os cálculos de planeamento usam valores declarados pelo utilizador, com origem e pressupostos identificados. O relatório não os transforma em resultados fiscais. Falta de imposto/parâmetro continua indeterminada, não zero; crédito/pedido/reconhecimento de IVA não se torna dinheiro recebido. A correcção de falhas de exportação e do rodapé não encerra a componente fiscal.
+
+**Implementação deste delta.** O exportador apresenta mensagens em português, identifica a operação e a referência de diagnóstico e mantém as selecções para nova tentativa pelo mesmo botão. A excepção original é registada na consola técnica local com operação/referência; não há novo envio ao servidor, telemetria nem registo de conteúdo do dossier/anexos. A consola é um diagnóstico local, não uma auditoria persistente no servidor. Uma guarda síncrona recusa outra execução enquanto a primeira está activa, mesmo antes da actualização do estado React; após erro a guarda é libertada. Preparação dos anexos é atómica: falhas/limites não substituem a lista existente nem as legendas. A selecção repetida do mesmo nome com os mesmos bytes mantém uma entrada; bytes diferentes com o mesmo nome e nomes diferentes continuam distintos. Esta identidade é escolha de implementação local, não regra de cadastro/publicação documental. Os limites de quantidade/tamanho já existentes não foram alterados.
+
+**Provas reutilizadas.** Data inválida; A/B e nova sessão; recusa de outra conta; histórico24/12 e hashes; resolvedor temporal sintético; controlos financeiros independentes; Word/CSV e respectivos valores; PDF nativo10 páginas/rodapé/última página; inventários/documentos e leitura SSH sem escrita. A Tempo aceitou o fecho do rodapé segundo as provas apresentadas e declarou que não abriu a imagem/PDF pelos caminhos locais. Não lhe atribuir inspecção visual directa. Os testes temporais sintéticos não representam legislação. A prova de recusa do clone com superutilizador é da aplicação; não é uma nova certificação de RLS. Não repetir as provas aceites apenas para gerar uma nova lista de resultados.
+
+**Ensaio dirigido isolado.** `http://127.0.0.1:18576/qa/export-recovery` usa o componente real e os geradores reais, com uma falha única de biblioteca injectada no módulo de ensaio, sem alteração das rotas de produção. Os controlos de falha e os ficheiros sintéticos ficam em `outputs/`, fora do Git e do pacote. Os contadores referem-se a chamadas/generações; para ZIP contam a geração interna de Word e a preparação do arquivo, não duas transferências. No ensaio de nova tentativa de PDF é omitida apenas a impressão automática, para observar a janela com conteúdo e não repetir a prova nativa aceite. Nenhuma dessas injecções entra na candidata funcional.
+
+**Procedimento de integração após revisão.** Fixar o commit candidato e manifesto de fontes; obter o `main` remoto actualizado e reconciliar apenas os deltas dos programadores que afectem estas fontes/consumidores. Rever o diff e conferir no ambiente QA a revisão exacta a integrar; repetir apenas verificações afectadas por conflitos ou alterações posteriores. Este delta não contém migrations, cadastro de regras, importação, publicação de documentos, contas, permissões ou alterações de MFA/configuração. Após decisão da Tempo, integrar pelo processo Git existente; confirmar o recibo da cadeia e a revisão efectivamente servida em `/build/revision.json`, com consulta pública e login privado conferidos nos consumidores afectados. Uma falha deve conservar a release anterior; não editar a pasta servida para contornar a cadeia. A reversão usa o mecanismo de release anterior de código/build, preservando base, anexos, configuração e dados posteriores; não repor um dump antigo. Se uma futura entrega incluir regras/dados activos, exigir o procedimento específico já aprovado de backup/restauro e acção autenticada; esse trabalho não está incluído aqui.
+
+### Diagnóstico fiscal separado da candidata — 21/10/2026
+
+| Camada | Existente e comprovado | Saldo efectivo |
+|---|---|---|
+| Fontes | Inventário anterior de9901 caminhos e32 candidatos por nome; três originais versionados: BR248/I/Suplemento1/2025, republicação Lei22/2022 no BR250/2.ºSuplemento e BR89/2017. Análises em `primary-text-review-2025-2026.md`, `official-source-register.md`, `fiscal-reform-2026-review.md` e referências em `fiscal-source-references-2026-10-06.csv`. | Reutilizar conteúdo, hashes, versões e citações já disponíveis; não pedir novamente esses documentos. A enumeração de caminhos não equivale à leitura de todos os binários. Distinguir fontes já lidas de fontes só inventariadas e alterações/anexos ainda sem correspondência. |
+| Parâmetros executáveis | Leitura administrativa de todos os estados confirmou zero linhas em `simulation_tax_rule_versions` tanto na QA como na homologação. A homologação tem seis referências em `investment_legal_sources`, ligadas a estruturas territoriais; não são taxas/fórmulas prontas. | Cadastrar por componente: código/versão, diploma/artigo/versão/hash, âmbito e condições, início/fim de aplicação, valor/unidade, bases/limites/exclusões, fórmula e arredondamento fundamentados. Os campos necessários variam por regra; não preencher lacunas por zero ou pela taxa mais recente. |
+| Governação e consulta | Modelo versionado, controlador de transições, API de resolução por componente/período/contexto, selecção de publicados e compatibilidade de versão da fonte; resolução temporal e indeterminação já ensaiadas. | Reutilizar estes serviços; conferir as correspondências documentais e a operação com parâmetros reais quando estes existirem. Não criar aprovações, nomeações ou uma nova exigência organizacional por escolha técnica. A Tempo define os papéis e as regras. |
+| Expressões | `SimulationTaxRuleExpression` já valida e avalia a DSL `investmoz.tax.v1` com aritmética racional, arredondamento e valores em falta. | Não reconstruir o avaliador. Verificar se cada regra fundamentada cabe na linguagem existente e estender apenas operações concretamente necessárias. |
+| Execução fiscal integrada | `RunSimulation` executa `base × taxa/100 × (1−redução/100)`, identifica `custom_planning`, `legal_interpretation=false`, `ruleset_version=null` e moeda não indicada nesse cenário. Consulta/DSL não são consumidas por este fluxo como motor fiscal. | Desenvolver orquestração explícita de componente/período/âmbito → regras elegíveis → entradas e parâmetros → avaliação → resultado e explicação com fontes/versões imutáveis. Tratar ambiguidade/transição/ausência como indeterminação. Manter o cenário de planeamento separado, sem o relabelar como imposto calculado. |
+| Resultado, dossier e relatório | Snapshots, histórico e exportadores existentes podem transportar resultados e proveniência; relatórios actuais identificam pressupostos/estimativas. | Integrar o resultado fiscal com identificação própria de regra, período, unidade/moeda, base, passos, arredondamento e lacunas. Guardar reprodução histórica e demonstrar casos de referência por regra, isolamento e não reaplicação de uma versão actual a um resultado antigo. |
+
+**Componentes a parametrizar, não taxas inventadas.** O acervo já analisado identifica famílias de alterações para ICE (Lei7/2025/tabela), ISPC (Lei9/2025), IVA (republicação Lei22/2022 e Lei10/2025, além da consolidação/rectificação aplicável), IRPS (Lei11/2025) e IRPC (Lei12/2025). A API também contempla INSS, retenções e direitos aduaneiros. Isto é inventário de domínios, não prova de cobertura documental completa nem autorização para aplicar uma taxa genérica. Para ICE/aduaneiro são relevantes código/unidade/tabela e período; para IVA, operação, incidência/exclusões/dedução e estado de reembolso; para ISPC, elegibilidade/limites e obrigações; para IRPS/IRPC, categoria, residência/estabelecimento, base, retenções e regimes específicos. Prazos, taxas, anexos e incentivos só entram com correspondência documental aplicável.
+
+A aceitação das fontes oficiais determinada pela Tempo em08/10 prevalece sobre pedidos históricos genéricos de reconfirmação de autenticidade ou de um fiscalista adicional. Identificar o artigo, âmbito, período, alterações/revogação e parâmetros é aplicação/rastreabilidade da fonte aceite, não segunda validação da sua credibilidade. A biblioteca documental, a situação jurídica e a utilização em cálculo são estados independentes; importar ou publicar documentos nunca activa cálculo fiscal.
+
+**Desenvolvimento fiscal necessário:** correspondência documental e cadastro versionado; adaptação concreta de expressões quando necessária; orquestração do cálculo; contrato de resultado/proveniência/histórico; ligação à interface/relatórios e casos de referência por componente/período. Nenhuma dessas frentes é encerrada por corrigir crédito, orçamento, tesouraria, falhas de exportação ou rodapé. O esforço integral deve ser dimensionado por regras/componentes e lacunas documentais identificadas; não cabe na estimativa de1–2h do recorte de exportação.
+
+### Fecho do recorte de exportações e saldo da candidata — 21/10/2026
+
+| Item existente | Saldo consolidado da candidata | Prova / limite |
+|---|---|---|
+| AUD-SIM-INT01 | Concluído no recorte | Validação de data: prova anterior reutilizada. |
+| AUD-SIM-INT02 | Parcial; implementação fiscal integral aberta | Zero regras remotas/QA; fontes, cadastro e integração discriminados no diagnóstico separado. |
+| AUD-SIM-INT03 | Concluído nas provas delimitadas | A/B/nova sessão e recusas anteriores; tesouraria com API/nova sessão e UI/recarga, sem alegar uma nova prova browser da mesma sessão. Limite RLS mantido. |
+| AUD-SIM-INT04 | Concluído no recorte demonstrado | Histórico/snapshots e resolvedor sintético reutilizados; integração real fiscal permanece em02. |
+| AUD-SIM-INT05 | Concluído nos controlos delimitados | Controlos independentes e provas financeiras aceites reutilizados; sem validação legal de impostos. |
+| AUD-SIM-INT06 | Concluído na apresentação/comparação deste relatório | Rodapé nativo aceito segundo provas; sem repetir10páginas/valores/CSV; sem atribuir inspecção local ao utilizador. |
+| AUD-SIM-INT07 | Concluído no recorte dirigido QA |3falhas de geração/retoma, anexo16MB recusado com lista conservada, re-selecção sem duplicação e ZIP íntegro; injecção sintética fora da entrega. |
+| AUD-SIM-INT08 | Concluído nos consumidores afectados | Mensagens portuguesas/diagnóstico técnico separado; limites de catálogo/governação mantidos, sem certificação global. |
+
+Esforço restante do recorte de engenharia de exportações:0h; revisão consolidada e eventual integração continuam pendentes. As1–2h anteriores foram estimativa deste recorte; não eram estimativa da implementação fiscal integral. Não fechar a revisão integral do simulador nem AUD-SIM-INT02 por este incremento. Word/PDF/ZIP foram ensaiados no componente real com falhas sintéticas de geração de um invólucro QA privado; ficheiros de67bytes e16MiB seleccionados manualmente pelo utilizador, estados observados directamente pelo Codex. A primeira recusa encontrou lista vazia e não foi usada como prova de preservação; a sequência posterior demonstrou lista válida→recusa16MB mantendo1→re-selecção válida mantendo1. ZIP real verificado por bytes, entrada única, título e secção. Leitura transitória falhada e concorrência demonstradas nos testes dirigidos, não por avaria real do sistema de ficheiros. A limitação anterior da selecção automática não foi contornada: a selecção normal foi manual. Os detalhes técnicos permanecem em diagnóstico local; não foi criado serviço de recolha remoto.
+
+Provas actuais em outputs/simulator-continuation-20261020/: export-word-error-20261021.*, export-pdf-error-20261021.txt, export-pdf-retry-20261021.txt, export-zip-error-20261021.*, export-zip-retry-20261021.txt, attachment-limit-preserved-20261021.*, attachment-duplicate-retry-20261021.*, export-zip-content-proof-20261021.json e export-recovery-candidate-20261021.json. O procedimento de integração e diagnóstico fiscal imediatamente anteriores integram esta mesma candidata e o mesmo registo; sem matriz/backlog adicional.
diff --git a/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv b/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
index f2e61250..7fc86b55 100644
--- a/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
+++ b/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
@@ -10651,11 +10651,11 @@ AUD-SEARCH-T09,Consistência transversal da pesquisa e navegação — Educaçã
AUD-SEARCH-T10,Consistência transversal da pesquisa e navegação — Biblioteca,Instruções expressas da Tempo na conversa de 20/10/2026; AGENTS.md; RF-MN-010 e AUD-GEO-01 preservados.,navegação/pesquisa,/documentos,"portal/services; portal/document — Resumo único nomeado Documentos, chips removíveis, controlos vazios ocultos sem apagar valores seleccionados, rodapé comum.",Sem alteração remota nesta execução; revisão apenas na branch codex/opportunity-search.,HTTP/Inertia e navegador: vazio e termos preservados; retorno documental existente conservado.,QA — delta delimitado; revisão Tempo pendente,Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,,"Filtros, contagem, resultados e URL coerentes; universos identificados; erro distinto de vazio; permissões e contexto conservados.",P1,,RF-MN-010; AUD-GEO-01,,,,,,,,,,,"Dois resumos de contagem, filtros activos sem remoção individual, controlos sem opções e rodapé local repetido.",Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,portal/services; portal/document; SearchState; SearchFeedback; TerritoryFields; portalNavigation,,"Integração em main apenas após revisão; assistência NLP, contratos e P7 separados.",Correcção/simplificação em QA,,HTTP/Inertia e navegador: vazio e termos preservados; retorno documental existente conservado.,Pesquisa transversal QA 20/10/2026,20/10/2026,,,,,,,,,,Provas comuns cobrem o componente reutilizado; HTTP vazio não demonstra operações de gestão ou publicação. Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,,falha funcional; navegação; apresentação visual,,Disponível para revisão na aplicação QA local.
AUD-SEARCH-T11,Consistência transversal da pesquisa e navegação — Legislação,Instruções expressas da Tempo na conversa de 20/10/2026; AGENTS.md; RF-MN-010 e AUD-GEO-01 preservados.,navegação/pesquisa,/legislacao,portal/services; portal/document — Reutiliza a correcção da biblioteca e preserva filtros jurídicos/documentais pertinentes.,Sem alteração remota nesta execução; revisão apenas na branch codex/opportunity-search.,HTTP/Inertia: resources.total=0; consumidor e query pública partilhados.,QA — delta delimitado; revisão Tempo pendente,"Situação jurídica, consulta e cálculo continuam independentes.",,"Filtros, contagem, resultados e URL coerentes; universos identificados; erro distinto de vazio; permissões e contexto conservados.",P1,,RF-MN-010; AUD-GEO-01,,,,,,,,,,,Mesmo padrão da biblioteca; não deve expor um universo concorrente.,"Situação jurídica, consulta e cálculo continuam independentes.",portal/services; portal/document; SearchState; SearchFeedback; TerritoryFields; portalNavigation,,"Integração em main apenas após revisão; assistência NLP, contratos e P7 separados.",Correcção/simplificação em QA,,HTTP/Inertia: resources.total=0; consumidor e query pública partilhados.,Pesquisa transversal QA 20/10/2026,20/10/2026,,,,,,,,,,"Provas comuns cobrem o componente reutilizado; HTTP vazio não demonstra operações de gestão ou publicação. Situação jurídica, consulta e cálculo continuam independentes.",,falha funcional; navegação; apresentação visual,,Disponível para revisão na aplicação QA local.
AUD-GUIDE-CARD-20261020,"Related educational cards: image, source summary, clear actions",Tempo 20/10/2026; independent delta after 0e7d51f18fb4,educational presentation,/sectores/{slug}; /explorar/{group}; articles; /oportunidades and detail,EducationalArticleCard; EducationalGuides; LegacyContent; SectorInvestment,QA only,1 test / 8 assertions; PHP syntax; TypeScript/build; desktop2048/mobile390; keyboard,QA review pending,Normal QA sector and article verified against existing library resource 10 and local image 25; previous dossier proof retained,,Source-derived summary; public images; conditional opportunity action; context preserved,P1,,,,,,,,,,,,,,,,,,presentation,,,,20/10/2026,,,,,,,,,,,,content; navigation; visual presentation,,Ready for QA review
-AUD-SIM-INT01,Invalid one-off fiscal date can throw instead of returning validation state,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Fixed in QA; invalid-date checks; 38 directed frontend tests passed,Previous inline-date proof retained; unchanged delta not repeated,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P0,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
-AUD-SIM-INT02,Review actual fiscal parameters sources periods and eligibility,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Verification pending; no parameter activation,QA zero rules verified with full visibility; prepared archive and analyses reused; current homologation read awaits SSH authentication,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P0,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
-AUD-SIM-INT03,Review isolation recovery across projects and sessions,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing controls and accepted proofs to reconcile; no leak established,Two dossiers and new login recovered in browser; cashflow persistence corrected and HTTP-tested; new visual cashflow delta pending,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P0,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
-AUD-SIM-INT04,Review stale and historical results and correct dossier,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing versions/fingerprints; targeted verification pending,Historical results visible after fix; 12 and 24 recovered; hashes unchanged; synthetic temporal resolver versions verified in memory only,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
-AUD-SIM-INT05,Independent financial controls unknown zero units and currencies,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Reconciliation pending; no invented tax assumptions,Independent business-plan and cashflow ledgers passed; complete credit recipe included in screen and exports,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
-AUD-SIM-INT06,Generated reports screen download and pagination,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing exporters; examples for this review still pending,Normal UI CSV and DOCX match shared values; all six DOCX pages checked; native Edge PDF awaits user save; new cashflow visual output pending,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
-AUD-SIM-INT07,Explicit validate calculate save export errors and retry,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing idempotency; consumer-level verification pending,Calculation navigation and failed-save retry fixed and browser-verified; normal downloads verified; interactive attachment blocked by extension permission,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
-AUD-SIM-INT08,Portuguese across portal and simulator outputs,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,"Partial QA fix: rate labels, password confirmation/security and spinner; wider inventory pending",Generic HTTP and fiscal-expression validation messages translated; status/correlation verified; selectable translations and source titles preserved,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,,,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT01,Invalid one-off fiscal date can throw instead of returning validation state,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Fixed in QA; invalid-date checks; 38 directed frontend tests passed,Previous inline-date proof retained; unchanged delta not repeated,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P0,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,, | [Saldo consolidado21/10/2026] Concluído no recorte. Nenhum delta de validação de data por demonstrar; prova anterior preservada. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação.,,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT02,Review actual fiscal parameters sources periods and eligibility,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Verification pending; no parameter activation,QA zero rules verified with full visibility; prepared archive and analyses reused; current homologation read awaits SSH authentication,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P0,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,," | [Leitura SSH 21/10/2026 08:17 Maputo] Zero regras em simulation_tax_rule_versions na homologação, incluindo todos os estados por leitura administrativa sem ocultação RLS. Seis referências em investment_legal_sources; não são parâmetros executáveis. QA também tinha zero regras. BEGIN READ ONLY/SELECT/ROLLBACK; zero escritas. Prova homologation-fiscal-readonly.json. O git HEAD registado é do checkout consultado, não certifica a revisão do build servido. A ausência de cadastro não é ausência de fontes oficiais nem reabre a aceitação da Tempo de 08/10. Não implementa a ligação funcional ao motor fiscal. | [Saldo consolidado21/10/2026] Parcial. Leitura remota concluída: zero regras de todos os estados na homologação, tal como QA; seis referências jurídicas não são parâmetros executáveis. Falta cadastro fundamentado por componente/âmbito/período e ligação funcional ao motor fiscal. Fontes e análises existentes reutilizáveis; aceitação oficial da Tempo de08/10 preservada. Não activar taxas nem importar/publicar por esta reconciliação. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação. | [Candidata21/10/2026] Diagnóstico fiscal separado no manual existente: fontes/analises já disponíveis; zero parâmetros executáveis na QA e homologação por leitura de todos os estados; governação/resolvedor temporal/DSL existentes; RunSimulation ainda aritmética personalizada sem consumir regras fiscais. Saldo: cadastro fundamentado, orquestração, contrato de resultado/histórico e ligação ao dossier/relatório, com casos por componente/período. Nenhuma regra criada nem activada; implementação fiscal integral aberta e excluída das1–2h de exportações.",,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT03,Review isolation recovery across projects and sessions,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing controls and accepted proofs to reconcile; no leak established,Two dossiers and new login recovered in browser; cashflow persistence corrected and HTTP-tested; new visual cashflow delta pending,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P0,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,"[Retoma 21/10/2026] QA 18576, clone simulator_review_delta_20261020_test: sessão sintética renovada por login normal; gravação autenticada e recarga recuperaram saldo 123, receita 900, custos 600, calendário mensal 10/vazio/0, crédito IVA estimado 500. Caixa conhecida 3713 MZN; total indeterminado desde mês 2; crédito estimado excluído da caixa. Prova visual cashflow-recovered-20261021.png e snapshot .txt em outputs/simulator-continuation-20261020. Não certifica recuperação destes novos valores após outro login, CSV/DOCX ou PDF nativo. Ligação de controlo do navegador perdida durante espera de download; não atribuir falha à aplicação. Leitura remota aguarda identificação da ligação SSH; zero alterações no destino. | [Saldo consolidado21/10/2026] Concluído no recorte. A/B, logout/novo login, recuperação e recusa pela aplicação demonstrados anteriormente. A tesouraria tem prova API de nova sessão e prova visual de recuperação por recarga. Não atribuir ao navegador nova sessão dos valores de tesouraria, nem nova certificação RLS; limites expressos conservados. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação.",,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT04,Review stale and historical results and correct dossier,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing versions/fingerprints; targeted verification pending,Historical results visible after fix; 12 and 24 recovered; hashes unchanged; synthetic temporal resolver versions verified in memory only,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,," | [Saldo consolidado21/10/2026] Concluído no recorte demonstrado. Histórico24/12 visível, hashes preservados e versões temporais sintéticas do resolvedor conferidas. Execução fiscal integrada com parâmetros reais pertence ao saldo de02 e não foi demonstrada por estes testes. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação.",,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT05,Independent financial controls unknown zero units and currencies,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Reconciliation pending; no invented tax assumptions,Independent business-plan and cashflow ledgers passed; complete credit recipe included in screen and exports,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,"[Retoma 21/10/2026] QA 18576, clone simulator_review_delta_20261020_test: sessão sintética renovada por login normal; gravação autenticada e recarga recuperaram saldo 123, receita 900, custos 600, calendário mensal 10/vazio/0, crédito IVA estimado 500. Caixa conhecida 3713 MZN; total indeterminado desde mês 2; crédito estimado excluído da caixa. Prova visual cashflow-recovered-20261021.png e snapshot .txt em outputs/simulator-continuation-20261020. Não certifica recuperação destes novos valores após outro login, CSV/DOCX ou PDF nativo. Ligação de controlo do navegador perdida durante espera de download; não atribuir falha à aplicação. Leitura remota aguarda identificação da ligação SSH; zero alterações no destino. | [Saldo consolidado21/10/2026] Concluído nos controlos delimitados. Controlos independentes de caixa/plano/crédito, zero/desconhecido e moedas preservados. Não são validação de taxas legais nem certificação de toda a contabilidade. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação.",,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT06,Generated reports screen download and pagination,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing exporters; examples for this review still pending,Normal UI CSV and DOCX match shared values; all six DOCX pages checked; native Edge PDF awaits user save; new cashflow visual output pending,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,,"[Retoma 21/10/2026] QA 18576, clone simulator_review_delta_20261020_test: sessão sintética renovada por login normal; gravação autenticada e recarga recuperaram saldo 123, receita 900, custos 600, calendário mensal 10/vazio/0, crédito IVA estimado 500. Caixa conhecida 3713 MZN; total indeterminado desde mês 2; crédito estimado excluído da caixa. Prova visual cashflow-recovered-20261021.png e snapshot .txt em outputs/simulator-continuation-20261020. Não certifica recuperação destes novos valores após outro login, CSV/DOCX ou PDF nativo. Ligação de controlo do navegador perdida durante espera de download; não atribuir falha à aplicação. Leitura remota aguarda identificação da ligação SSH; zero alterações no destino. | [Exportação nativa 21/10/2026] Saída actual aberta pelo botão do portal: revisão 4, 12 meses, MZN, saldo inicial123/receita900/custos600, calendário10/vazio/0, caixa conhecida3713 e total indeterminado coincidem com o ecrã. Crédito estimado500 identificado como pressuposto, não somado à caixa. Prova portal-print-current-20261021.txt. Relatório de20/10/revisão2 preservado, sem o confundir com o actual. Downloads: sem novo CSV na pasta habitual ou nos temporários locais conferidos; isso não demonstra falha nem cancelamento. Histórico de downloads bloqueado pela política da ferramenta; caminho do ficheiro solicitado antes de repetir. PDF nativo aberto, mas paginação/legibilidade aguardam o ficheiro efectivamente guardado pelo Edge; conversão DOCX/PDF anterior não conta como essa prova. Perda da ligação e bloqueio de controlo durante impressão são limitações da ferramenta, sem falha do simulador demonstrada. | [Fecho da verificação dos ficheiros 21/10/2026] Transferências Windows redireccionada para \\Mac\Home\Downloads; CSV concluído08:12:46, PDF nativo08:17:19. Sem repetir downloads. Os12 registos mensais do CSV coincidem exactamente com o snapshot do ecrã após correspondência de colunas; PDF revisão4 conserva valores mensais, MZN,12meses,123/900/600, crédito estimado500 não caixa e caixa conhecida3713. Os10 PNG do PDF nativo foram inspeccionados: defeito confirmado na linha repetida de rodapé, sobreposta ao corpo perto do topo de páginas, incluindo2,6e10. Conteúdo/valores conferidos; paginação/legibilidade não aceites até correcção e nova prova nativa. Não é conversão DOCX/PDF. Perda de ligação continua limitação da ferramenta e não causou falha do download; sobreposição é defeito distinto demonstrado no PDF. Provas: download-native-inspection-20261021.json, portal-cashflow-20261021.csv, portal-native-20261021.pdf e native-pdf-render/. A indicação anterior de ficheiros pendentes fica superada por esta prova. Sem alteração funcional nem escrita remota. | [Correcção do rodapé nativo QA 21/10/2026] Origem: pedido expresso da Tempo nesta conversa; solução de implementação, sem regra organizacional nova. Causa em createProjectDossierPrintHtml (project-dossier-document.ts): footer position:fixed/bottom:-14mm sobrepunha a área fragmentada de impressão. Substituído na impressão por caixas @page @bottom-left/@bottom-right, dentro da margem inferior reservada20mm, com identificação/revisão e número de página/total. Rodapé normal de ecrã conservado; sem diminuir letras do corpo (10,5pt), tabelas, cabeçalhos ou origens (9pt), nem retirar conteúdo. Mesmo dossier B/revisão4 regenerado pelo botão do portal QA18576 e guardado no Edge, não por conversão DOCX. 10→10 páginas A4; comparação automática do corpo por página, descontando apenas hora de emissão/rodapé/contador, coincide integralmente. Inspecção visual dos10 PNG: sem sobreposição, cabeçalhos de tabela repetidos, quebras/linhas preservadas, última página íntegra e numeração1/10→10/10. Rodapés medidos inteiramente na margem inferior. Ecrã QA conferido após build; estilos screen e geradores DOCX/ZIP inalterados por comparação de fontes. 10 testes do exportador, TypeScript e build passaram; escape da revisão na nova string CSS verificado. Reutilizadas provas de valores e CSV aceites; não repetido download/aritmética. Provas: native-footer-fix-20261021.json; portal-native-fixed-20261021.pdf; native-footer-before-after-20261021.jpg; native-pdf-fixed-render/; screen-after-print-fix-20261021.png. Fechado exclusivamente o defeito de rodapé neste relatório QA; limitações e restantes critérios de AUD-SIM-INT06 mantêm âmbito próprio. Relato anterior de sobreposição fica superado neste delta pela comparação antes/depois. Branch codex/simulator-integrated-review separada de main, sem integração, escrita remota ou disponibilização activa; revisão prevista mantém-se pendente. | [Saldo consolidado21/10/2026] Concluído na apresentação e comparação deste relatório. Rodapé do PDF nativo fechado em QA segundo provas apresentadas;10 páginas/valores/CSV não repetidos. Tempo declarou que não abriu imagem/PDF pelos caminhos locais: registar aceitação das provas, não revisão visual directa do utilizador. Outras provas de relatório conservadas; falhas interactivas de exportação/anexos mantêm saldo em07. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação.",,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT07,Explicit validate calculate save export errors and retry,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,Existing idempotency; consumer-level verification pending,Calculation navigation and failed-save retry fixed and browser-verified; normal downloads verified; interactive attachment blocked by extension permission,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,," | [Saldo consolidado21/10/2026] Parcial. Gravação503→nova tentativa→recuperação e exportações normais demonstradas. Faltam falhas dirigidas de geração Word/ZIP/PDF e retoma; teste interactivo de limite de anexo não ocorreu por bloqueio da ferramenta antes do envio. Nova leitura do código: três catch apresentam cause.message para Error, podendo mostrar texto técnico sem tradução. Sem nova falha de execução alegada. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação. | [Candidata21/10/2026] Concluído o recorte dirigido em QA: Word/PDF/ZIP falha única injectada→mensagem portuguesa→nova tentativa no mesmo botão. ZIP preserva título editado, secção desmarcada e anexo; arquivo real contém uma só cópia original/hash igual. Recusa16MB observada mantendo1anexo; nova selecção válida limpa erro e mantém1entrada. Guarda síncrona impede concorrência/duplicação; teste de falha de leitura preserva lista/legenda e permite retoma.4testes dirigidos passaram, TypeScript/build passaram. UI usa componente/geradores reais num invólucro QA sintético; a injecção e a omissão da impressão automática nesse ensaio não integram a entrega. Não repetidas10páginas/valores/CSV aceites.",,20/10/2026,,,,,,,,,,,,,,
+AUD-SIM-INT08,Portuguese across portal and simulator outputs,Tempo request 20/10/2026; integrated simulator review; same manual,simulator and shared language,,,QA only,"Partial QA fix: rate labels, password confirmation/security and spinner; wider inventory pending",Generic HTTP and fiscal-expression validation messages translated; status/correlation verified; selectable translations and source titles preserved,QA continuation verified; precise open inputs and cashflow visual check in same manual; 2-4 h remaining,,,P1,,,,,,,,,,,,,,,,,,diagnosis and targeted corrections,," | [Saldo consolidado21/10/2026] Parcial. Inventário estático,404 real e traduções de validação preservados. Classificar/apresentar em português os erros dinâmicos das bibliotecas de exportação (cause.message, três consumidores) e conferir estados residuais/governação delimitados; não certificar todos os textos dinâmicos do catálogo. Ver saldo dos oito itens no manual existente; sem fecho global por esta reconciliação. | [Candidata21/10/2026] Mensagens dinâmicas dos exportadores Word/ZIP/PDF/CSV e leitura de anexos usam texto português por operação, preservação e nova tentativa com referênciaEXP. Excepção original só na consola técnica local com referência/operação; sem telemetria nem auditoria remota novas. UI confirmou português nas3falhas de geração;4testes verificam separação mensagem/diagnóstico e correlação em5operações. Traduções/404/validações anteriores reutilizados. Fecho dos consumidores afectados, não certificação de todos os textos de catálogo ou nova sessão administrativa de governação.",,20/10/2026,,,,,,,,,,,,,,
diff --git a/resources/js/components/project-dossier-export.tsx b/resources/js/components/project-dossier-export.tsx
index b506c52c..2500796f 100644
--- a/resources/js/components/project-dossier-export.tsx
+++ b/resources/js/components/project-dossier-export.tsx
@@ -1,11 +1,15 @@
-import { useMemo, useState } from 'react';
+import { useMemo, useRef, useState } from 'react';
+import {
+ DossierExportGate,
+ dossierExportFailure,
+ prepareDossierAttachments,
+} from '@/lib/dossier-export-state';
import {
createProjectDossierPrintHtml,
createProjectDossierReport,
dossierReportSections,
generateProjectDossierDocx,
generateProjectDossierPackage,
- validateDossierAttachments,
type DossierAttachment,
type DossierReference,
type DossierCurrentCalculation,
@@ -57,6 +61,8 @@ export function ProjectDossierExport({
const [attachments, setAttachments] = useState([]);
const [error, setError] = useState('');
const [busy, setBusy] = useState('');
+ const [notice, setNotice] = useState('');
+ const exportGate = useRef(new DossierExportGate());
const selected = useMemo(
() => attachments.filter((item) => item.include),
[attachments],
@@ -66,20 +72,33 @@ export function ProjectDossierExport({
[selectedSections],
);
- function addFiles(files: FileList | null): void {
+ async function addFiles(files: FileList | null): Promise {
if (!files?.length) return;
const incoming = Array.from(files);
- const combined = [...attachments.map((item) => item.file), ...incoming];
- const problem = validateDossierAttachments(combined);
- if (problem) {
- setError(problem);
- return;
- }
- setAttachments((current) => [
- ...current,
- ...incoming.map((file) => ({ file, include: true, caption: '' })),
- ]);
- setError('');
+ await exportGate.current.run(async () => {
+ setBusy('attachments');
+ setNotice('');
+ try {
+ const result = await prepareDossierAttachments(
+ attachments,
+ incoming,
+ );
+ if (result.problem) {
+ setError(result.problem);
+ return;
+ }
+ setAttachments(result.attachments);
+ setError('');
+ if (result.duplicateCount)
+ setNotice(
+ 'Os ficheiros que já estavam na lista foram mantidos uma única vez.',
+ );
+ } catch (cause) {
+ setError(dossierExportFailure('attachments', cause));
+ } finally {
+ setBusy('');
+ }
+ });
}
function toggleSection(id: DossierReportSectionId, checked: boolean): void {
@@ -118,99 +137,103 @@ export function ProjectDossierExport({
}
async function exportWord(): Promise {
- setBusy('word');
- setError('');
- try {
- const report = model();
- const blob = await generateProjectDossierDocx(
- report,
- selected,
- selectedSections.has('annexes'),
- );
- download(
- blob,
- `relatorio-investmoz-${filenameStem(report.title)}.docx`,
- );
- } catch (cause) {
- setError(
- cause instanceof Error
- ? cause.message
- : 'Não foi possível gerar o relatório Word.',
- );
- } finally {
- setBusy('');
- }
+ await exportGate.current.run(async () => {
+ setBusy('word');
+ setError('');
+ try {
+ const report = model();
+ const blob = await generateProjectDossierDocx(
+ report,
+ selected,
+ selectedSections.has('annexes'),
+ );
+ download(
+ blob,
+ `relatorio-investmoz-${filenameStem(report.title)}.docx`,
+ );
+ } catch (cause) {
+ setError(dossierExportFailure('word', cause));
+ } finally {
+ setBusy('');
+ }
+ });
}
async function exportPackage(): Promise {
- setBusy('package');
- setError('');
- try {
- const report = model();
- const docx = await generateProjectDossierDocx(
- report,
- selected,
- selectedSections.has('annexes'),
- );
- const archive = await generateProjectDossierPackage(
- docx,
- selected,
- selectedSections.has('annexes'),
- );
- download(
- archive,
- `relatorio-investmoz-${filenameStem(report.title)}-anexos.zip`,
- );
- } catch (cause) {
- setError(
- cause instanceof Error
- ? cause.message
- : 'Não foi possível preparar o pacote de anexos.',
- );
- } finally {
- setBusy('');
- }
+ await exportGate.current.run(async () => {
+ setBusy('package');
+ setError('');
+ try {
+ const report = model();
+ const docx = await generateProjectDossierDocx(
+ report,
+ selected,
+ selectedSections.has('annexes'),
+ );
+ const archive = await generateProjectDossierPackage(
+ docx,
+ selected,
+ selectedSections.has('annexes'),
+ );
+ download(
+ archive,
+ `relatorio-investmoz-${filenameStem(report.title)}-anexos.zip`,
+ );
+ } catch (cause) {
+ setError(dossierExportFailure('package', cause));
+ } finally {
+ setBusy('');
+ }
+ });
}
async function exportPdf(): Promise {
- const printWindow = window.open('about:blank', '_blank');
- if (!printWindow) {
- setError(
- 'O browser bloqueou a janela de impressão. Permita pop-ups para abrir a versão PDF.',
- );
- return;
- }
- setBusy('pdf');
- setError('');
- try {
- const html = await createProjectDossierPrintHtml(
- model(),
- selected,
- selectedSections.has('annexes'),
- );
- printWindow.document.open();
- printWindow.document.write(html);
- printWindow.document.close();
- } catch (cause) {
- printWindow.close();
- setError(
- cause instanceof Error
- ? cause.message
- : 'Não foi possível preparar a versão para PDF.',
- );
- } finally {
- setBusy('');
- }
+ await exportGate.current.run(async () => {
+ const printWindow = window.open('about:blank', '_blank');
+ if (!printWindow) {
+ setError(
+ 'O browser bloqueou a janela de impressão. Permita pop-ups para abrir a versão PDF.',
+ );
+ return;
+ }
+ setBusy('pdf');
+ setError('');
+ try {
+ const html = await createProjectDossierPrintHtml(
+ model(),
+ selected,
+ selectedSections.has('annexes'),
+ );
+ printWindow.document.open();
+ printWindow.document.write(html);
+ printWindow.document.close();
+ } catch (cause) {
+ printWindow.close();
+ setError(dossierExportFailure('pdf', cause));
+ } finally {
+ setBusy('');
+ }
+ });
}
- function exportCsv(): void {
- const blob = new Blob([exportProjectDossierCsv(draft)], {
- type: 'text/csv;charset=utf-8',
+ async function exportCsv(): Promise {
+ await exportGate.current.run(async () => {
+ setBusy('csv');
+ setError('');
+ try {
+ const blob = new Blob([exportProjectDossierCsv(draft)], {
+ type: 'text/csv;charset=utf-8',
+ });
+ download(
+ blob,
+ `dossier-projecto-investmoz-${filenameStem(String(draft.project_title ?? ''))}.csv`,
+ );
+ } catch (cause) {
+ setError(dossierExportFailure('csv', cause));
+ } finally {
+ setBusy('');
+ }
});
- download(
- blob,
- `dossier-projecto-investmoz-${filenameStem(String(draft.project_title ?? ''))}.csv`,
- );
}
const totalBytes = attachments.reduce(
@@ -261,6 +284,7 @@ export function ProjectDossierExport({
>
toggleSection(
@@ -298,9 +322,10 @@ export function ProjectDossierExport({
id="project-report-files"
type="file"
multiple
+ disabled={Boolean(busy)}
accept="image/jpeg,image/png,text/csv,text/plain,.csv,.tsv,.txt,.pdf,.doc,.docx,.xlsx,.odt"
onChange={(event) => {
- addFiles(event.currentTarget.files);
+ void addFiles(event.currentTarget.files);
event.currentTarget.value = '';
}}
/>
@@ -322,6 +347,7 @@ export function ProjectDossierExport({
updateAttachment(index, {
@@ -340,6 +366,7 @@ export function ProjectDossierExport({
+ {notice && (
+
+ {notice}
+
+ )}
{error && (
{error}
@@ -414,7 +447,7 @@ export function ProjectDossierExport({
type="button"
className="rounded border px-4 py-2"
disabled={Boolean(busy)}
- onClick={exportCsv}
+ onClick={() => void exportCsv()}
>
Exportar CSV complementar
diff --git a/resources/js/lib/dossier-export-state.ts b/resources/js/lib/dossier-export-state.ts
new file mode 100644
index 00000000..12eda97d
--- /dev/null
+++ b/resources/js/lib/dossier-export-state.ts
@@ -0,0 +1,89 @@
+import {
+ validateDossierAttachments,
+ type DossierAttachment,
+} from './project-dossier-report.ts';
+
+export type DossierExportOperation =
+ | 'word'
+ | 'package'
+ | 'pdf'
+ | 'csv'
+ | 'attachments';
+const messages: Record = {
+ word: 'Não foi possível gerar o relatório Word.',
+ package: 'Não foi possível preparar o pacote de anexos.',
+ pdf: 'Não foi possível preparar a versão para PDF.',
+ csv: 'Não foi possível preparar o ficheiro CSV.',
+ attachments: 'Não foi possível ler os anexos seleccionados.',
+};
+let failureSequence = 0;
+
+export function dossierExportFailure(
+ operation: DossierExportOperation,
+ cause: unknown,
+ log: (message: string, detail: unknown) => void = console.error,
+): string {
+ const reference = `EXP-${Date.now().toString(36)}-${++failureSequence}`;
+ // Local diagnostics only: never send dossier values or file contents.
+ log('[InvesteMoz exportação]', { reference, operation, cause });
+ return `${messages[operation]} Os dados, as secções e os anexos foram mantidos. Tente novamente pelo mesmo botão. Referência: ${reference}.`;
+}
+
+/** Synchronous acquisition prevents a second click before React renders busy. */
+export class DossierExportGate {
+ private active = false;
+ async run(task: () => Promise): Promise {
+ if (this.active) return false;
+ this.active = true;
+ try {
+ await task();
+ return true;
+ } finally {
+ this.active = false;
+ }
+ }
+}
+
+export async function prepareDossierAttachments(
+ current: DossierAttachment[],
+ incoming: File[],
+): Promise<{
+ attachments: DossierAttachment[];
+ duplicateCount: number;
+ problem?: string;
+}> {
+ for (const file of incoming) {
+ const problem = validateDossierAttachments([file]);
+ if (problem)
+ return { attachments: current, duplicateCount: 0, problem };
+ }
+ const identity = async (file: File) => {
+ const hash = await crypto.subtle.digest(
+ 'SHA-256',
+ await file.arrayBuffer(),
+ );
+ return `${file.name}:${Array.from(new Uint8Array(hash), (b) => b.toString(16).padStart(2, '0')).join('')}`;
+ };
+ const known = new Set(
+ await Promise.all(current.map((item) => identity(item.file))),
+ );
+ const added: DossierAttachment[] = [];
+ let duplicateCount = 0;
+ for (const file of incoming) {
+ const key = await identity(file);
+ if (known.has(key)) {
+ duplicateCount++;
+ continue;
+ }
+ known.add(key);
+ added.push({ file, include: true, caption: '' });
+ }
+ const problem = validateDossierAttachments(
+ [...current, ...added].map((item) => item.file),
+ );
+ return {
+ attachments: problem ? current : [...current, ...added],
+ duplicateCount,
+ problem: problem ?? undefined,
+ };
+}
diff --git a/resources/js/lib/project-dossier-document.ts b/resources/js/lib/project-dossier-document.ts
index 8edd15e3..6d28f078 100644
--- a/resources/js/lib/project-dossier-document.ts
+++ b/resources/js/lib/project-dossier-document.ts
@@ -659,8 +659,13 @@ export async function createProjectDossierPrintHtml(
content.push('
Não há informação fornecida nesta secção.
');
content.push('');
}
+ // Page margin boxes reserve footer space on every printed page. A fixed
+ // body element can overlap fragmented tables in Chromium's print layout.
+ const printFooter = JSON.stringify(
+ `InvesteMoz · Relatório privado · ${model.version}`,
+ ).replaceAll('<', '\\3c ');
return `Relatório — ${escapeHtml(model.title)}
InvesteMoz Relatório consolidado do projecto
${escapeHtml(model.title)} Gerado em ${escapeHtml(new Date(model.generatedAt).toLocaleString('pt-MZ'))} Versão/revisão: ${escapeHtml(model.version)}
Documento privado. O portal não publica nem partilha este conteúdo.