9.7 KiB
Revisão de Arquitectura, Dados, Segurança, QA e Produto
Data: 26/09/2026. Âmbito: carteira territorial, importação/publicação e assistência interna de IA, incluindo integração com o percurso do investidor. Revisão estática do código e dos testes existentes; não constitui auditoria integral do portal ou teste de intrusão. Nesta revisão não foram alterados código aplicacional, dados ou aprovações.
A decisão do proprietário de aprovar a carteira e permitir aprovação pelo próprio gestor foi respeitada. Os problemas abaixo não exigem regressar à regra de duas pessoas.
Actualização de implementação — 28/09/2026
R1 corrigido na aplicação local. As fichas têm version_no; guardar e publicar comparam a versão enviada com a linha bloqueada na transacção e recusam versões antigas com HTTP 409. Ambas as operações incrementam a versão, incluindo publicação pela importação documental. O editor renova os formulários após cada alteração e impede publicar enquanto houver alterações locais por guardar. A aprovação pelo próprio gestor autorizado mantém-se.
O teste de regressão cobre gravação concorrente, publicação obsoleta, repetição da publicação, ausência de versão, preservação do conteúdo e ocultação dos metadados internos na página pública. Suite completa: 138 testes e 1.463 verificações; PHPStan, TypeScript, lint e build aprovados. Migration aplicada após backup/restauro verificado de 93 tabelas. As 29 fichas existentes mantiveram-se publicadas, na versão inicial 1.
R2–R5 permanecem pendentes desta revisão. A versão editorial resolve concorrência; não constitui, por si só, o histórico completo de conteúdo solicitado em R3. Os achados abaixo conservam o diagnóstico original de 26/09/2026.
Achados por prioridade
R1 — Alta: publicação não está vinculada à versão vista pelo gestor
Referências: app/Http/Controllers/InvestmentPortfolioController.php:95, resources/js/pages/portfolio/show.tsx, app/Services/PortalAudit.php:16.
O pedido de publicação envia apenas a evidência de aprovação. O servidor bloqueia e publica a linha mais recente, sem comparar uma versão ou hash apresentado ao gestor. Se A abre uma ficha, B altera o conteúdo e A publica a partir da página antiga, fica publicado o conteúdo de B que A não viu. O bloqueio transaccional serializa escritas, mas não detecta uma página desactualizada. A gravação do formulário também permite substituir alterações concorrentes.
Correcção: acrescentar versão monotónica; enviar a versão nos pedidos de guardar/publicar e comparar dentro da transacção. Responder 409 e pedir recarregamento quando divergir. Preservar a possibilidade de o próprio gestor aprovar.
QA de aceitação: dois clientes abrem a versão N; um guarda N+1; guardar ou publicar com N deve falhar sem mudar conteúdo ou publicação. Publicar N+1 deve passar.
R2 — Alta: resultados históricos de qualidade e prazos não revalidam classificação
Referências: app/Http/Controllers/AiController.php:69, app/Services/Ai/AssistiveRules.php:66 e :92, app/Services/Ai/EvidenceRepository.php:55.
As regras de qualidade e prazos filtram registos públicos/internos ao calcular o resultado. Contudo, esses resultados não têm source_ids documentais e a leitura posterior só verifica suspensão da capacidade; existem verificações adicionais para triagem e recomendações, mas não para qualidade/prazos. Depois de uma tarefa, lead ou geometria ser eliminado ou reclassificado como restrito, o resultado antigo continua a expor identificadores, relações, regras e, nas tarefas, prazos. A exposição é a gestores autorizados, não ao público, e não inclui necessariamente o texto integral do registo.
Correcção: registar dependências estruturadas por tipo/ID e revalidar existência, classificação e autorização ao mostrar ou aceitar o resultado. Ocultar o resultado ou remover os itens inelegíveis, de forma explícita.
QA de aceitação: gerar resultado, reclassificar/eliminar uma dependência e confirmar que leitura e aceitação não disponibilizam o item. Incluir leads, tarefas e geometrias.
R3 — Média: auditoria de publicação não permite reconstruir o conteúdo aprovado
Referências: app/Services/PortalAudit.php:20, app/Http/Controllers/InvestmentPortfolioController.php:84, app/Console/Commands/ImportInvestmentPortfolio.php:45.
A auditoria genérica conserva nomes de campos alterados e alguns estados, mas não a versão/hash do conteúdo publicado. Guardar a ficha apaga a evidência anterior da linha corrente. O comando de importação regista hashes do dataset e da autorização, o que melhora essa operação específica, mas o fluxo de edição/publicação manual não oferece equivalência. Consequentemente, o histórico permite saber quem publicou, mas não reconstruir com precisão o texto e a decisão daquela publicação após alterações.
Correcção: conservar revisões imutáveis da ficha e da decisão em armazenamento com acesso restrito; referenciar revisão e hash no evento de auditoria, mantendo texto livre fora do log genérico.
QA de aceitação: publicar, editar e republicar; recuperar separadamente as duas versões e respectivas decisões sem expor evidência no endpoint público.
R4 — Média: cadastro e ficha pública podem divergir
Referências: app/Http/Controllers/InvestmentStructureController.php (save), app/Http/Controllers/InvestmentPortfolioController.php:84, database/seeders/InvestmentPortfolioSeeder.php.
O cadastro de projectos/clusters e a ficha documental são editáveis em percursos diferentes. Alterar nome/descrição no cadastro não actualiza nem sinaliza a ficha pública; editar a ficha não actualiza o cadastro. O seeder preserva ambas as edições. Assim, a gestão pode mostrar um nome ou descrição diferente do que o investidor consulta sem indicar que a publicação é uma versão anterior.
Correcção: definir a ficha como revisão editorial explícita do cadastro, guardar a versão de origem e mostrar aviso de divergência com acção de preparar nova revisão. Evitar sincronização automática que publique alterações sem aprovação.
QA de aceitação: alterar cadastro de uma ficha publicada e verificar aviso de divergência, preservação da versão pública e reconciliação aprovada.
R5 — Média: recomendações da IA não incluem a carteira publicada
Referência: app/Services/Ai/AssistiveRules.php:17.
A capacidade recommend consulta apenas Opportunity::published(). Os 29 dossiers territoriais estão em investment_dossiers, ligados a projectos, clusters e corredores. A sua publicação não os torna candidatos à recomendação. Para um utilizador que procura projectos âncora pela assistência, os resultados podem ficar vazios embora existam fichas públicas relevantes.
Correcção: explicitar o âmbito da capacidade na interface e, para cobrir a carteira, acrescentar consulta com tipos e filtros próprios, autorização e links para os dossiers. Não duplicar projectos como oportunidades apenas para contornar a separação dos modelos.
QA de aceitação: pesquisa por um projecto documental publicado deve devolvê-lo no modo que declarar cobertura da carteira; rascunhos e entidades eliminadas permanecem excluídos.
Avaliação transversal
| Área | Evidência e conclusão |
|---|---|
| Arquitectura | Laravel centraliza autorização e persistência; serviços de IA separados de controllers. R1 e R4 mostram necessidade de versões explícitas entre edição, cadastro e publicação. |
| Dados | Importação transaccional/idempotente, códigos documentais e relações preservados. Valores indicativos continuam em texto. R3 impede reconstituição completa do histórico editorial. |
| Segurança | Rotas de gestão exigem autenticação, email verificado e manage-portal; resultados IA encriptados e fontes documentais revalidadas. R2 deixa uma lacuna equivalente nas dependências estruturadas. |
| QA | Execução anterior registada: 119 testes / 1.107 verificações, PHPStan, Pint, TypeScript e build aprovados. Não repetidos nesta revisão. Os cenários de concorrência e reclassificação acima precisam de cobertura; testes verdes não os demonstram. |
| Produto | Consulta territorial, relações, painel e manifestação de interesse estão disponíveis. A assistência continua lexical/determinística e a integração externa SuiteCRM não foi executada. R5 limita a descoberta da carteira via IA. |
Ordem de tratamento
- R1: versões e conflito de edição/publicação.
- R2: revalidação das dependências estruturadas de IA.
- R3 e R4: histórico editorial e reconciliação cadastro/ficha.
- R5: cobertura e clareza do âmbito da recomendação.
Não foi identificado um achado crítico no código examinado. Os dois achados altos devem ser corrigidos antes de ampliar a utilização concorrente ou tratar dados sujeitos a reclassificação. Esta conclusão técnica não revoga a aprovação já concedida pelo proprietário.