Files
SGF/docs/IDENTITY_DELIVERY.md

11 KiB

Entrega do primeiro percurso funcional

Implementação local sobre o SGF_TEMPO_Roteiro_v0_9.docx e a avaliação anterior. Destino: C:\laragon\www\sgf-tempo. Sem reinstalação, mudança de versões, publicação, acesso ao InvesteMoz ou módulos financeiros.

Funcional

  • Autenticação real por email/palavra-passe com sessão, limitação de tentativas por identidade/IP, regeneração na entrada e invalidação na saída.
  • Se não existir utilizador no ambiente local, o ecrã explica a preparação pendente; não apresenta um login que ainda não pode funcionar.
  • Selecção explícita de empresa e unidade, contexto visível, pertenças e permissões revalidadas no servidor a cada pedido.
  • Consulta e edição dos nomes existentes; criação de unidades exige concessão própria e atribui ao criador consulta e edição explícitas apenas da unidade criada (consequência aprovada pelo utilizador).
  • Concessões persistidas como dados, separadas de tenant/empresa/unidade, sem privilégio por nome/email e sem «todas as unidades».
  • Gestão de acessos limitada à empresa activa e aos direitos detidos pelo gestor, incluindo os direitos dependentes abrangidos por revogação.
  • Tokens de contexto recusam gravações de formulários anteriores à mudança de empresa/unidade. Identificadores manipulados são rejeitados.
  • Triggers PostgreSQL impedem transferir identificadores de empresas, unidades, pertenças e concessões em operações em massa. Auditoria append-only conserva alterações de nomes e acessos, com actor/âmbito/motivo e sem credenciais/tokens.
  • Procedimentos locais de pré-visualização, criação de utilizador/primeiro âmbito e recuperação de credencial/concessões. Exigem confirmação concreta, operador e motivo; não usam administração PostgreSQL.

Delta de base de dados aplicado

Base de destino: sgf_tempo_dev, cluster próprio 127.0.0.1:55432, migrações executadas por sgf_dev_owner. A aplicação continua a usar sgf_dev_app.

  1. 2026_10_25_010000_add_identity_workflow.php: users.auth_version, chave composta de unidades, tabelas permission_grants e identity_audit, índices/constraints de âmbito e triggers de propriedade/auditoria.
  2. 2026_10_25_020000_lock_membership_identifiers.php: trigger adicional de imutabilidade das chaves de company_memberships.

Alterações aditivas, ensaiadas primeiro em sgf_tempo_test. Não houve reset/fresh/wipe ou eliminação de dados em desenvolvimento. A base estava sem utilizadores, tenants, empresas ou unidades antes da operação inicial; nenhum dado sintético foi colocado nela. Eventos de utilização local permanecem na auditoria.

Ficheiros principais

Grupo Ficheiros
Autenticação e HTTP routes/web.php, IdentityController.php, RequireValidSession.php, RequireCompanyContext.php
Regras e auditoria IdentityWorkflow.php, Permissions.php, Audit.php, LocalDatabaseGuard.php
Fundação reutilizada CompanyContext.php, Unit.php, User.php, AppServiceProvider.php; sem recriação de modelos
Procedimentos locais ProvisionIdentityUser.php, RecoverIdentityUser.php, scripts/identity-status.php
Interface resources/js/app.jsx, resources/css/app.css
Configuração local config/identity.php, caminhos opcionais de sessões/cache, ignores dos artefactos de prova
Provas tests/Support/IdentityFixture.php, IdentityWorkflowTest.php, adaptação de CompanyIsolationTest.php, browser-proof.ps1, http-proof.mjs, prepare-browser-fixture.php
Documentação README, AGENTS, IDENTITY_WORKFLOW.md e este relatório

O seeder de exemplo deixou de criar uma conta com credencial previsível. Os lockfiles e as versões directas mantiveram-se.

Resultados

PHPUnit: 27 testes, 112 asserções aprovadas. Compilação Vite concluída. composer check-platform-reqs aprovado. O incremento não instalou dependências nem alterou versões: PHP 8.4.27 x64 NTS, Laravel 13.38.0, React/React DOM 19.2.9, Node 24.22.1 ARM64, npm 11.19.1, Vite 8.3.5, PHPUnit 12.5.40, PostgreSQL 17.11.

Critério Evidência
Entrada inválida/válida e saída Testes com credenciais; login real no Edge com conta sintética e saída verificada
Sessão antiga não reutilizável Prova HTTP real, replay do cookie anterior à saída: 401
Empresa/unidade não autorizadas Testes e HTTP: 403; navegador abriu directamente unidade não autorizada e mostrou recusa
Consulta sem edição Testes/API: 403; navegador mostrou apenas leitura, sem botão de gravação
Revogação no pedido seguinte Dois clientes HTTP independentes: concessão permitiu edição (200), revogação recusou o pedido seguinte (403)
Formulário de contexto anterior Testes e prova HTTP: 409
Identificadores e operações em massa Testes de payload manipulado e triggers de empresa, unidade, pertença e concessão
Delegação superior à própria Testes e prova HTTP com gestor limitado: 403
Protecção dos pedidos Prova HTTP sem CSRF/origem válida: 419; ambiente de navegador mantém protecção activa
Destino dos testes Guard existente preservado; comando destrutivo contra desenvolvimento recusado; procedimentos locais recusam base de testes

As provas visuais usam apenas sgf_tempo_test, na porta 8001, com sessões/cache/cookie separados. Não se confundem com a conta real nem com os testes actingAs. O servidor temporário foi parado e os dados sintéticos da prova foram eliminados pela recriação posterior exclusivamente da base de testes. A credencial temporária foi removida do ficheiro local; não foi incluída nos relatórios.

Capturas:

Primeiro administrador

Foi confirmada a operação concreta: tenant Tempo Lda, empresa Tempo Lda e Osmane Nala (nala@tempo.co.mz), com company.view, company.edit, unit.create e access.manage exclusivamente nessa empresa. Sem unidades iniciais e sem acessos universais.

A palavra-passe só pode ser definida pelo utilizador no terminal local, com entrada oculta. O assistente não a recebe no chat nem a define por omissão. O procedimento aprovado está em C:\laragon\data\sgf-tempo\run\complete-first-admin.ps1. A confirmação da operação não equivale à conta já criada: verificar a conclusão com scripts/identity-status.php e a mensagem de sucesso do terminal.

Uma primeira tentativa de abertura automática do terminal foi rejeitada pela revisão automática; uma invocação simples do script já preparado abriu depois uma janela PowerShell normal. A instrução ao utilizador é confirmar com yes, definir a palavra-passe e repeti-la (a entrada não ecoa caracteres), e actualizar o estado no navegador.

Limites

Este incremento não decide o isolamento de produção entre clientes nem implementa RLS, MFA, auto-registo, email, anexos, exportações, filas de negócio, fiscalidade, contabilidade ou planos comerciais. O escopo Eloquent é apenas uma camada: endpoints/serviços verificam autorização, constraints/trigger protegem relações e identificadores e os testes demonstram os caminhos incluídos. SQL administrativo e o operador do sistema continuam sujeitos a responsabilidades próprias; isto não é certificação de isolamento para produção.

O catálogo de acções suportadas está no código e as concessões estão nos dados. Não foi construído um motor geral de parâmetros ou toda a experiência Camaleão. Reutilizam-se cadastros e contexto sem copiar empresas/unidades por utilizador. A recuperação local preserva concessões ao alterar uma credencial; a recuperação excepcional de gestão requer outro plano explícito e confirmação, sem administrador universal.

Correcção da recolha inicial de credencial

O procedimento aprovado usa agora Read-Host -AsSecureString do PowerShell. A confirmação da operação já dada na sessão é preservada; a credencial e a repetição seguem apenas pela entrada padrão do processo, com identidade/consentimento explícitos, sem argumentos ou ficheiros de segredos. O transporte foi verificado com entrada sintética aleatória contendo Unicode e espaços; a sintaxe PowerShell também foi validada. A suite passou com 30 testes e 117 asserções. A criação real continua dependente da conclusão dos dois pedidos protegidos pelo utilizador local.

Conta inicial concluída

A criação foi concluída pelo utilizador no terminal local. Verificação posterior: Osmane Nala, nala@tempo.co.mz; tenant e empresa Tempo Lda; uma pertença e exactamente quatro concessões de empresa (company.view, company.edit, unit.create, access.manage); nenhuma unidade inicial. O guard local e a verificação de privilégios da aplicação passaram. A palavra-passe não foi consultada pelo assistente. Não repetir o procedimento de criação; usar o login e, se necessário, recuperação local assistida.

Verificação final para aceitação

Em 25 de Outubro de 2026, a sessão real de Samira foi verificada no navegador: consulta de Tempo Lda e SEGI com campos só de leitura, sem botões de gravação/criação/gestão. A abertura directa de /api/accesses foi recusada. Foi removida a selecção de unidade, confirmada a limpeza do contexto e novamente seleccionada SEGI. A saída regressou ao ecrã de entrada e uma recarga permaneceu sem autenticação. Capturas: proofs/09-samira-read-only.png e proofs/10-real-session-logout.png.

Os direitos de Osmane foram conferidos por leitura e confrontados com as provas anteriores no navegador: gestão de acessos e consulta/edição da empresa, criação de unidades e consulta/edição explícitas da SEGI. Não foi iniciada outra sessão de Osmane nesta verificação nem consultada qualquer palavra-passe.

Estado na verificação: entrega tecnicamente pronta para aceitação do utilizador, no âmbito local e com os limites documentados. A verificação técnica pelo assistente não substitui essa aceitação nem autoriza implementação financeira ou publicação. Prestação de serviços permanece apenas em especificação.

Aceitação e encerramento pelo utilizador

Em 25 de Outubro de 2026, o utilizador declarou:

Aceito e dou por concluído o incremento local de entrada, contexto e permissões, no âmbito demonstrado e com os limites documentados em IDENTITY_DELIVERY.md. Preserva esta entrega como base. Serviços mantém-se apenas em especificação; não autorizo ainda implementação financeira nem publicação.

Estado actual: aceite e concluído, exclusivamente no âmbito local demonstrado. Preservar esta entrega e as respectivas provas como base dos incrementos seguintes. Esta aceitação não amplia as funcionalidades, não elimina os limites documentados e não autoriza implementação financeira ou publicação.