128 lines
11 KiB
Markdown
128 lines
11 KiB
Markdown
# Estado do projeto e handoff
|
|
|
|
**Atualizado em:** 4 de agosto de 2026
|
|
**Fase:** Fases 1 a 6 concluídas; Fase 7 em curso (base técnica de identidade, saúde e recuperação concluída)
|
|
**Último agente:** Codex
|
|
|
|
## Resultado disponível
|
|
|
|
- Projeto oficial Laravel 13 React Starter Kit criado.
|
|
- Autenticação local via Fortify, recuperação de palavra-passe, verificação de email, 2FA e passkeys.
|
|
- Registo público desativado conforme o plano.
|
|
- Estrutura relacional de utilizadores, identidades externas, perfis e permissões.
|
|
- Cache local de ativos Snipe-IT.
|
|
- Modelo completo inicial para reservas, itens, aprovações, bloqueios, entrega/devolução, sincronizações e auditoria.
|
|
- Proteção PostgreSQL contra períodos sobrepostos para o mesmo equipamento através de `EXCLUDE USING gist` e intervalos `[início, fim)`.
|
|
- Serviço de disponibilidade que considera estado local, atribuição, reservas e bloqueios.
|
|
- Criação transacional de uma requisição pendente com vários equipamentos e registo de auditoria.
|
|
- Dashboard pessoal, catálogo com pesquisa/filtros, formulário de nova requisição e histórico.
|
|
- Docker Compose com Nginx, PHP-FPM, PostgreSQL, Redis, Node/Vite, filas, scheduler e Mailpit.
|
|
- Dados fictícios e duas contas locais para desenvolvimento.
|
|
- Cliente Snipe-IT autenticado com paginação, timeout, retry seletivo e validação de respostas.
|
|
- Sincronização convergente de ativos com histórico, hash de conteúdo, lock, job único e desativação apenas após execução completa.
|
|
- Comando `snipe:sync-assets`, execução horária e painel de diagnóstico exclusivo para administradores.
|
|
- Pesquisa do catálogo por início/fim que exclui atribuições atuais, reservas bloqueantes e bloqueios administrativos.
|
|
- Propagação do período consultado do catálogo para o formulário e consulta atualizável de equipamentos livres.
|
|
- Cancelamento pelo próprio requisitante, com validação de estado, libertação transacional dos itens e auditoria.
|
|
- Expiração de pré-reservas vencidas através do comando `reservations:expire` e job único agendado a cada cinco minutos.
|
|
- Calendário mensal pessoal, isolado por utilizador e com navegação entre meses.
|
|
- Área de aprovação protegida por perfil, com pesquisa por referência/requisitante.
|
|
- Aprovação, rejeição e pedido de esclarecimentos transacionais, registados em `approval_actions` e `audit_logs`.
|
|
- Aprovação revalida disponibilidade e estado operacional do ativo antes de promover itens `held` para `reserved`.
|
|
- Notificações assíncronas por email e base de dados para submissões, decisões, esclarecimentos e substituições.
|
|
- Caixa interna de notificações, contador de não lidas, marcação individual/coletiva e isolamento por utilizador.
|
|
- Resposta auditada do requisitante a esclarecimentos, com regresso a `pending_approval` e novo prazo de 48 horas.
|
|
- Substituição de equipamento apenas por ativo livre da mesma categoria, mantendo a pré-reserva e todo o histórico.
|
|
- Fila de aprovação com filtros por referência, requisitante, categoria e período, incluindo histórico de ações.
|
|
- Cliente Snipe-IT operacional com token separado, checkout para utilizador, check-in para a localização habitual e validação de erros transportados em HTTP 200.
|
|
- Área diária do operador protegida pelo perfil `inventory_operator`/`administrator`, com leitura por scanner-teclado ou pesquisa de referência, requisitante, etiqueta e ID Snipe-IT.
|
|
- Preparação, entrega, devolução e conclusão com máquina de estados, condição física, observações, operador, destinatário e resposta externa em `handover_records`.
|
|
- Associação persistente entre o utilizador do portal e o respetivo ID no Snipe-IT, confirmada durante uma entrega bem-sucedida.
|
|
- Tratamento explícito de falhas parciais: movimentos já aceites são preservados, a requisição passa a `incident` e a falha fica em `audit_logs` para reconciliação.
|
|
- Registo de falta, atraso e incidente; um incidente pode criar um bloqueio temporal do equipamento que entra imediatamente no motor de disponibilidade.
|
|
- Gestão administrativa de utilizadores com pesquisa, perfis múltiplos, estado ativo, departamento, ID Snipe-IT e reposição de palavra-passe.
|
|
- Proteção contra desativação da própria conta administrativa e contra remoção do último administrador ativo.
|
|
- Políticas de reserva editáveis para antecedência, duração, margem operacional, prazo de aprovação e limite de equipamentos.
|
|
- Margens temporais persistidas por item e garantidas pela restrição de exclusão PostgreSQL, sem reescrever reservas existentes quando a política muda.
|
|
- Calendário institucional global para aprovadores, operadores, administradores e auditores.
|
|
- Relatórios por período com totais, horas de utilização, incidentes, atrasos, estados, categorias, departamentos e equipamentos mais requisitados.
|
|
- Exportação CSV protegida contra formula injection e limitada a períodos de 366 dias.
|
|
- Consulta paginada e filtrável de `audit_logs`, apenas para administradores e auditores.
|
|
- Modelos editáveis de assunto/mensagem para os seis eventos de notificação, com variáveis validadas e auditoria das alterações.
|
|
- Autenticação Microsoft Entra/OIDC de tenant único com descoberta `.well-known`, Authorization Code Flow, PKCE, `state`, `nonce` e validação criptográfica RS256.
|
|
- Associação Microsoft explícita após login local e confirmação recente da palavra-passe; nenhuma conta é associada automaticamente por email.
|
|
- Login Microsoft para identidades previamente associadas, bloqueio de contas inativas e eventos de associação/login/remoção em auditoria.
|
|
- Endpoints `/health/live` e `/health/ready`, sendo readiness dependente de PostgreSQL e cache sem divulgar detalhes internos.
|
|
- Health check Docker do Nginx sobre readiness.
|
|
- Scripts operacionais de backup PostgreSQL custom com checksum e restauro de teste numa base temporária isolada.
|
|
- Checklist versionado de produção, incluindo Entra, Snipe-IT, SMTP/TLS, segredos, monitorização, recuperação, segurança e piloto.
|
|
|
|
## Limites conhecidos
|
|
|
|
- A integração está implementada e testada contra respostas simuladas; falta configurar e validar URL, versão e token da instância institucional. Até lá, o catálogo utiliza dados fictícios do seeder.
|
|
- Microsoft Entra ID está implementado e testado com tokens assinados simulados; falta registar/configurar a aplicação no tenant institucional e validar Conditional Access/MFA real.
|
|
- As notificações estão implementadas com Mailpit em desenvolvimento; falta validar SMTP institucional antes do piloto.
|
|
- O calendário atual é a vista mensal pessoal do MVP; vistas diária, semanal, global e por equipamento/categoria/localização ficam para as áreas operacional e administrativa.
|
|
- O leitor operacional aceita scanners QR/código de barras que funcionem como teclado. A leitura direta pela câmara do navegador ainda não foi adicionada.
|
|
- Uma falha depois de o Snipe-IT confirmar um movimento e antes do commit local é uma transação distribuída ambígua; não existe retry automático de escritas. O operador deve reconciliar pelos registos Snipe-IT e `audit_logs` conforme o runbook.
|
|
- As exportações administrativas estão disponíveis em CSV; XLSX poderá ser acrescentado se o processo institucional o exigir.
|
|
|
|
## Próxima tarefa recomendada
|
|
|
|
Implementar a **Fase 7 — hardening e entrada em produção**:
|
|
|
|
1. configurar e validar Microsoft Entra no tenant institucional, incluindo Conditional Access/MFA;
|
|
2. validar a integração contra o Snipe-IT institucional e configurar tokens reais de menor privilégio;
|
|
3. configurar SMTP institucional, domínio, HTTPS e gestão externa de segredos;
|
|
4. ligar os health checks a monitorização/alertas e agendar backups cifrados externos;
|
|
5. executar testes de segurança, concorrência, desempenho e end-to-end com equipamentos reais;
|
|
6. preparar formação, dados iniciais e piloto com um grupo reduzido;
|
|
7. corrigir resultados do piloto e preparar a disponibilização geral.
|
|
|
|
## Testes da última sessão
|
|
|
|
Validação concluída em 4 de agosto de 2026:
|
|
|
|
- `docker compose exec -T app composer test`: passou;
|
|
- Laravel Pint: 141 ficheiros sem desvios;
|
|
- PHPStan/Larastan nível 7: 107 ficheiros, zero erros;
|
|
- Pest: 103 testes passaram, 585 asserções e 2 testes de registo ignorados por a funcionalidade estar deliberadamente desativada;
|
|
- TypeScript (`tsc --noEmit`): passou;
|
|
- ESLint: passou;
|
|
- Prettier: passou;
|
|
- Vite: builds cliente e SSR concluídos, 2314 módulos cliente e 103 módulos SSR transformados;
|
|
- PostgreSQL 17: `migrate:fresh --seed` concluído, incluindo extensão `btree_gist` e restrição de exclusão temporal;
|
|
- PostgreSQL 17: migration incremental do marcador `last_seen_sync_run_id` aplicada com sucesso;
|
|
- PostgreSQL 17: nenhuma migration pendente; comando de expiração executado e agendamentos horário/a cada cinco minutos confirmados;
|
|
- PostgreSQL 17: migration `notifications` aplicada com sucesso;
|
|
- PostgreSQL 17: migration `snipe_user_id` aplicada e fluxo operacional exercitado contra API simulada;
|
|
- PostgreSQL 17: migration de `portal_settings` e buffers temporais aplicada; restrição GiST recriada sobre o intervalo com margem;
|
|
- smoke test HTTP: `/login` respondeu com estado 200 através do Nginx;
|
|
- Vite em Docker: URL pública, HMR e CORS verificados em `localhost:5173`; corrigida a página em branco causada pela publicação anterior de `0.0.0.0:5173`;
|
|
- Inertia SSR: renderização do login validada através do serviço `node`; corrigido o componente de mensagens flash que usava `usePage()` fora do contexto Inertia;
|
|
- verificação visual no browser integrado: a inspeção controlada de `localhost` continua impedida por uma política administrativa temporariamente indisponível; aprovações, esclarecimentos e notificações foram validados por testes Inertia, TypeScript e builds cliente/SSR.
|
|
- testes focados de Microsoft Entra e health checks: 9 passaram, com 57 asserções;
|
|
- PHPStan/Larastan depois da integração OIDC: 107 ficheiros, zero erros;
|
|
- TypeScript, ESLint e Prettier depois das alterações de login/segurança: passaram;
|
|
- backup PostgreSQL real em formato custom criado com checksum e validado por `pg_restore --list`;
|
|
- restauro real numa base temporária: passou e confirmou 12 migrations antes da remoção automática;
|
|
- smoke tests via Nginx: `/health/live` devolveu `ok` e `/health/ready` devolveu `ready`.
|
|
- diagnóstico de login local: a base de desenvolvimento estava vazia apesar de migrada; `db:seed --force` repôs 2 utilizadores ativos, 5 perfis e 18 ativos fictícios, sem substituir dados existentes;
|
|
- login real no browser validado com `demo@escola.pt`: redirecionou para `/dashboard` e não produziu erros de consola.
|
|
|
|
## Decisões pendentes do contexto institucional
|
|
|
|
Estas decisões não bloqueiam o desenvolvimento com defaults seguros, mas devem ser confirmadas antes do piloto:
|
|
|
|
- versão e URL da instância Snipe-IT;
|
|
- categorias e estados requisitáveis;
|
|
- tenant, client ID e redirect URI do Entra ID;
|
|
- matriz final de aprovadores por categoria/departamento;
|
|
- duração máxima, antecedência e margens por categoria;
|
|
- domínio institucional e método de emissão TLS;
|
|
- SMTP institucional.
|
|
|
|
## Próximo ficheiro a abrir
|
|
|
|
Começar em `docs/PRODUCTION_CHECKLIST.md`. A próxima alteração de código pode preparar testes de concorrência/desempenho e observabilidade local; as validações Entra, Snipe-IT e SMTP só ficam concluídas quando existirem serviços institucionais concretos, sem guardar os respetivos segredos no repositório.
|