Preserva base local aceite de identidade e acessos
@@ -0,0 +1,105 @@
|
||||
# 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:
|
||||
|
||||
- [Entrada inválida](proofs/01-invalid-login.png)
|
||||
- [Empresa e unidade autorizadas](proofs/02-authorized-context.png)
|
||||
- [Gestão de acessos](proofs/03-access-management.png)
|
||||
- [Consulta sem edição](proofs/04-read-only-access.png)
|
||||
- [URL directa recusada](proofs/05-direct-url-refused.png)
|
||||
- [Saída](proofs/06-logged-out.png)
|
||||
- [Resultados HTTP sem segredos](proofs/http-results.json)
|
||||
|
||||
## 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.
|
||||
@@ -0,0 +1,70 @@
|
||||
# Utilização e recuperação local
|
||||
|
||||
## Contexto e permissões
|
||||
|
||||
Tenant é o cliente contratante, empresa é a entidade empresarial e unidade é uma subdivisão dessa empresa. Pertença ao tenant não autoriza as suas empresas. Pertença à empresa, por si só, também não concede operações: as permissões são linhas em `permission_grants`.
|
||||
|
||||
| Concessão | Âmbito | Efeito |
|
||||
| --- | --- | --- |
|
||||
| company.view | Empresa | Consultar e seleccionar empresa |
|
||||
| company.edit | Empresa | Editar apenas o nome da empresa |
|
||||
| unit.create | Empresa | Criar unidade; receber consulta/edição explícitas apenas da unidade criada |
|
||||
| access.manage | Empresa | Gerir concessões nesta empresa, limitado pelos próprios direitos |
|
||||
| unit.view | Unidade concreta | Consultar e seleccionar essa unidade |
|
||||
| unit.edit | Unidade concreta | Editar o nome dessa unidade, exigindo consulta e selecção dela |
|
||||
|
||||
Não existem papéis universais, privilégios por email ou acesso implícito a todas as unidades. Para conceder a edição de unidade é necessário conceder primeiro a consulta dessa unidade; para outros direitos é necessária consulta da empresa. Um gestor só pode conceder ou revogar direitos que possui no mesmo âmbito. A revogação de consulta de empresa remove os seus direitos dependentes apenas se o gestor tiver autoridade sobre todos eles; caso contrário é recusada. A revogação de consulta de uma unidade remove também a sua edição nas mesmas condições. Estas dependências são registadas na auditoria.
|
||||
|
||||
A mudança de empresa limpa a unidade anterior. Cada selecção gera um token de contexto; um pedido de gravação com o token anterior é recusado com 409. Os formulários visíveis são recarregados quando o contexto muda. Identificadores recebidos são sempre revalidados no servidor. Mudanças de direitos aplicam-se no pedido seguinte; cada alteração revalida direitos dentro da transacção e partilha um bloqueio da empresa com as alterações de acessos.
|
||||
|
||||
## Preparar outro utilizador, sem acessos automáticos
|
||||
|
||||
Substituir os campos pelos dados expressamente autorizados. A execução sem `--apply` é apenas pré-visualização:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\sgf.ps1 php artisan identity:provision --email="EMAIL" --name="NOME" --operator="RESPONSAVEL" --reason="MOTIVO"
|
||||
```
|
||||
|
||||
Depois da confirmação da operação concreta, repetir com `--apply` num terminal interactivo. A palavra-passe é introduzida de forma oculta, duas vezes. Requer pelo menos 12 caracteres e até 72 bytes, respeitando o algoritmo bcrypt existente. A conta fica sem empresa e sem permissões até um gestor autorizado conceder os direitos pela interface, começando por `company.view`.
|
||||
|
||||
Para os primeiros acessos de uma empresa sem gestor, o mesmo comando aceita `--company=ID`, `--company-permission=PERMISSAO` repetido e `--unit-permission=ID:PERMISSAO` repetido. Não existe concessão por omissão. Para novo âmbito inicial, `--tenant-name` e `--company-name` são explícitos, exclusivos de `--company`, e não há reutilização por inferência. Se já houver gestor na empresa, a concessão deve ser feita pela interface dentro dos direitos desse gestor.
|
||||
|
||||
Todos os procedimentos locais recusam ambientes ou bases diferentes de `local` / `sgf_tempo_dev`, e exigem o papel de aplicação `sgf_dev_app`, não o administrador PostgreSQL.
|
||||
|
||||
## Recuperar palavra-passe
|
||||
|
||||
Verificar primeiro a identidade da pessoa e a autorização do responsável local. Não solicitar a credencial no chat. Pré-visualizar:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\sgf.ps1 php artisan identity:recover --email="EMAIL" --operator="RESPONSAVEL" --reason="MOTIVO"
|
||||
```
|
||||
|
||||
Só depois da confirmação da operação, repetir com `--apply` e definir a nova credencial nos dois pedidos ocultos do terminal. A alteração é transaccional, aumenta a versão de autenticação e invalida as sessões anteriores no pedido seguinte. As concessões são preservadas. O operador e o motivo ficam na auditoria; palavras-passe, hashes, cookies e tokens não são incluídos nela. Não colocar segredos no motivo.
|
||||
|
||||
## Recuperar gestão quando não resta gestor
|
||||
|
||||
Não há excepção automática nem administrador universal. O operador local deve pré-visualizar e obter confirmação de concessões exactas para uma empresa existente e utilizador existente:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\sgf.ps1 php artisan identity:provision --existing-user --email="EMAIL" --name="NOME_EXISTENTE" --company=ID --company-permission=company.view --company-permission=access.manage --operator="RESPONSAVEL" --reason="MOTIVO"
|
||||
```
|
||||
|
||||
A recuperação só é permitida se não existir concessão `access.manage` nessa empresa. Não altera a credencial, não cria outro tenant/empresa e não acrescenta direitos além dos explicitamente apresentados. `--apply` exige confirmação no terminal. Não usar SQL directo como procedimento habitual de recuperação.
|
||||
|
||||
## Prova de navegador com dados sintéticos
|
||||
|
||||
Nunca preparar contas de demonstração em desenvolvimento. Depois de parar outras provas e com as tabelas de teste vazias, iniciar:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\browser-proof.ps1 start
|
||||
```
|
||||
|
||||
A prova usa `sgf_tempo_test`, endereço 127.0.0.1:8001, cookie, sessões e cache próprios. O ambiente `browser-testing` mantém CSRF activo e aplica o mesmo guard do destino de testes. O script recusa uma base não vazia e não apaga dados. A credencial aleatória sintética fica apenas num ficheiro local com ACL restrita, nunca no relatório. Não executar a suite enquanto esta prova está activa.
|
||||
|
||||
```powershell
|
||||
C:\laragon\tools\sgf-tempo\node-v24.22.1-win-arm64\node.exe .\scripts\http-proof.mjs
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\browser-proof.ps1 stop
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\sgf.ps1 test
|
||||
```
|
||||
|
||||
Parar elimina o ficheiro temporário da credencial; o último teste recria apenas a base de testes e elimina os dados sintéticos da prova. Não apresentar esse ficheiro, palavras-passe, cookies ou tokens. As capturas guardadas em `docs/proofs` mostram apenas entidades sintéticas.
|
||||
@@ -0,0 +1,56 @@
|
||||
> Registo histórico da preparação inicial. O estado actual e as instruções de utilização estão no README e em IDENTITY_WORKFLOW.md.
|
||||
|
||||
# Registo da preparação local
|
||||
|
||||
Data: 25 de Outubro de 2026. Destino confirmado: `C:\laragon\www\sgf-tempo`.
|
||||
|
||||
## Versões efectivamente instaladas ou utilizadas
|
||||
|
||||
| Componente | Versão | Localização / origem |
|
||||
| --- | --- | --- |
|
||||
| Windows | 11 Pro ARM64, 10.0.26300 | Sistema existente |
|
||||
| PHP | 8.4.27 NTS VS17 x64 | C:\laragon\tools\sgf-tempo\php-8.4.27 |
|
||||
| Composer | 2.10.3 | C:\laragon\tools\sgf-tempo\composer-2.10.3\composer.phar |
|
||||
| Node.js | 24.22.1 ARM64 | C:\laragon\tools\sgf-tempo\node-v24.22.1-win-arm64 |
|
||||
| npm | 11.19.1 | Incluído nesse Node.js |
|
||||
| Esqueleto Laravel | 13.11.0 | laravel/laravel, sem scripts de criação automáticos |
|
||||
| Laravel Framework | 13.38.0 | composer.lock |
|
||||
| React / React DOM | 19.2.9 / 19.2.9 | package-lock.json |
|
||||
| Vite | 8.3.5 | package-lock.json |
|
||||
| Plugin React | 6.1.2 | package-lock.json |
|
||||
| Laravel Vite Plugin | 3.2.0 | package-lock.json |
|
||||
| brick/math | 0.14.8 | composer.lock |
|
||||
| PHPUnit | 12.5.40 | composer.lock |
|
||||
| Mockery | 1.6.12 | Dependência auxiliar dos testes, composer.lock |
|
||||
| PostgreSQL | 17.11 x64 | Binários existentes; cluster e configuração exclusivos |
|
||||
| Git | 2.55.0.windows.5 | Instalação existente; repositório local inicializado |
|
||||
|
||||
Sem substituições das versões propostas. PostGIS não foi activado e Python não foi instalado nem incorporado. A detecção anterior encontrou PostGIS 3.6.2 em ficheiros de extensão e Python 3.10.6 fora do PATH; nenhum é dependência desta entrega.
|
||||
|
||||
## Integridade e compatibilidade
|
||||
|
||||
Downloads de PHP, Node.js e Composer conferidos por SHA-256 contra metadados oficiais; arquivos e comprovativos estão em `C:\laragon\tools\sgf-tempo\downloads`. PHP x64 executou em Windows ARM64, carregou as extensões necessárias e executou Laravel/PHPUnit. Node ARM64 executou npm, a compilação e Vite. Resolução conjunta concluída sem ignorar requisitos de plataforma. Dependências transitivas exactas preservadas nos lockfiles.
|
||||
|
||||
Fontes: https://www.php.net/downloads.php, https://windows.php.net/downloads/releases/releases.json, https://nodejs.org/dist/v24.22.1/SHASUMS256.txt, https://getcomposer.org/download/2.10.3/composer.phar.sha256sum, https://repo.packagist.org e https://registry.npmjs.org.
|
||||
|
||||
## Verificações concluídas
|
||||
|
||||
- Composer check-platform-reqs: aprovado.
|
||||
- Composer validate --strict --no-check-all: aprovado. --no-check-all desactiva os avisos contra versões exactas, que são deliberados neste âmbito; as verificações de esquema e lock permanecem.
|
||||
- Composer audit e npm audit: sem vulnerabilidades conhecidas reportadas no momento da preparação.
|
||||
- Vite build: concluído; manifest e recursos gerados.
|
||||
- PHPUnit: 11 testes, 27 asserções aprovadas. Inclui acesso por pertença explícita, recusa entre empresas do mesmo tenant e de tenants diferentes, contexto ausente/limpo, escopo de leitura/escrita, modelo de contexto anterior, relação inválida na base e protecção do destino dos testes.
|
||||
- migrate:fresh --env=local: recusado pelo guard antes da execução destrutiva.
|
||||
- Aplicação de desenvolvimento: sgf_dev_app sem administração, sem CREATE no esquema e sem CONNECT à base de testes. Executor de testes sem CONNECT à base de desenvolvimento.
|
||||
- Base de desenvolvimento sem fixtures dos testes.
|
||||
- HTTP: /, /up e manifest com 200; /api/context sem autenticação com 401.
|
||||
- Vite serviu JSX transformado em ARM64, HTTP 200.
|
||||
- Colisão na porta 8000: arranque recusado, PIDs existentes preservados.
|
||||
- Paragem e novo arranque do cluster e servidor próprios: concluídos.
|
||||
- .env, .env.testing, vendor e node_modules ignorados pelo Git. Sem commit, remoto ou publicação.
|
||||
|
||||
## Limites e decisões pendentes
|
||||
|
||||
A demonstração é local e limitada à identidade/contexto. Não constitui isolamento de produção ou aceitação dos módulos. Permanecem pendentes estratégia de isolamento entre clientes, RLS, autenticação de produto, permissões detalhadas, propagação de contexto a filas/anexos/exportações, regras financeiras, fiscalidade, planos, preços, elegibilidade, quotas, fornecedores e operação dos futuros ambientes. As tabelas cache/jobs do esqueleto são apenas infraestrutura Laravel; esta entrega usa cache/sessões locais e fila síncrona, sem trabalhadores financeiros.
|
||||
|
||||
Não foram alterados o InvesteMoz, o serviço PostgreSQL existente, o PATH global ou a política global de execução. Servidor HTTP e cluster SGF ligam apenas a 127.0.0.1. Instruções de arranque e paragem no README.
|
||||
@@ -0,0 +1,207 @@
|
||||
# Primeiro percurso operacional de serviços
|
||||
|
||||
Data: 25 de Outubro de 2026.
|
||||
|
||||
Referência: SGF_TEMPO_Roteiro_v0_9.docx, particularmente secções 5, 14 a 19 e 20 a 24. Este documento especifica um percurso para revisão; não autoriza emissão fiscal, operações reais, movimentação de fundos ou implementação integral.
|
||||
|
||||
## Decisões já tomadas
|
||||
|
||||
- Começar pelo sector de prestação de serviços, com um serviço pontual como cenário de desenvolvimento.
|
||||
- Reutilizar a fundação existente: tenant, empresa, unidade, utilizador, sessão, contexto, concessões e auditoria.
|
||||
- Preservar independência do InvesteMoz, versões instaladas e separação entre desenvolvimento e testes.
|
||||
- Usar dados sintéticos nas provas, sem os inserir como operações da Tempo Lda/SEGI.
|
||||
|
||||
As entidades, estados, limites e entregas abaixo são propostas técnicas. Valores de teste não são preços comerciais, taxas fiscais ou regras contabilísticas aprovadas.
|
||||
|
||||
## Condição antes da implementação seguinte
|
||||
|
||||
O incremento de entrada, contexto e permissões tem implementação e provas técnicas documentadas em IDENTITY_DELIVERY.md. A verificação por leitura confirmou uma única SEGI, os direitos de gestão de Osmane na Tempo Lda e apenas company.view/unit.view para Samira na Tempo Lda/SEGI. A última suite executada passou com 30 testes e 117 asserções; não foi repetida nesta revisão documental.
|
||||
|
||||
O utilizador aceitou e deu por concluído o incremento local de entrada, contexto e permissões em 25 de Outubro de 2026, no âmbito demonstrado e com os limites de IDENTITY_DELIVERY.md. Preservar essa entrega como base. Limites conhecidos: âmbito local, sem MFA/RLS de produção, sem criação geral de contas pela interface e com procedimentos locais assistidos de recuperação. A aceitação está registada separadamente do cenário de serviços.
|
||||
|
||||
Nesta etapa está autorizada apenas a especificação de serviços. As entregas A/B/C abaixo são um plano para decisões posteriores, não uma ordem para as implementar agora.
|
||||
|
||||
## Resultado pretendido
|
||||
|
||||
Um utilizador autorizado escolhe um cliente e um serviço, regista a prestação, prepara a facturação, acompanha recebimentos parciais e uma correcção e consegue explicar o saldo pelas origens. Os acontecimentos alimentam captura contabilística permanente, incluindo pendências. Reconciliação e fecho só são apresentados como concluídos quando cumprirem os controlos aprovados.
|
||||
|
||||
Percurso de referência:
|
||||
|
||||
Cliente → serviço → prestação → documento de facturação → recebimento parcial → correcção → segundo recebimento → reconciliação → fecho.
|
||||
|
||||
Os acontecimentos têm identidades e estados próprios. A prestação não é uma factura e uma factura não comprova recebimento. Registar um recebimento não inicia pagamento, transferência ou débito bancário.
|
||||
|
||||
| Acontecimento | Significado | O que não demonstra por si só |
|
||||
| --- | --- | --- |
|
||||
| Serviço prestado | Registo do trabalho realizado, cliente, conteúdo, unidade e data da prestação | Factura emitida, pagamento recebido ou reconhecimento contabilístico aprovado |
|
||||
| Factura | Documento de cobrança com identidade, data, linhas e regras próprias | Serviço concluído ou dinheiro recebido |
|
||||
| Recebimento | Observação/registo de um valor recebido, com origem/evidência e afectação | Emissão de factura, liquidação confirmada pela fonte ou reconciliação concluída |
|
||||
|
||||
Conservar separadamente datas, estados, identificadores e relações desses três acontecimentos. Não criar os três como efeito implícito de um único botão.
|
||||
|
||||
## Cenário sintético de aceitação
|
||||
|
||||
Entidades exclusivamente de teste: Empresa Exemplo de Serviços, Unidade de Teste, Cliente Exemplo e Serviço Pontual de Teste. Não utilizar os nomes, contas ou operações reais da Tempo Lda como fixtures.
|
||||
|
||||
Para demonstrar as relações e a aritmética do sub-razão, usar o seguinte exemplo em MZN. O valor 1 000,00 é um montante de referência artificial do teste; não significa preço aprovado, tributação nula ou montante fiscal já apurado.
|
||||
|
||||
### Caso principal liquidação por dois recebimentos
|
||||
|
||||
| Acontecimento | Valor do teste | Saldo aritmético por receber |
|
||||
| --- | ---: | ---: |
|
||||
| Documento de referência do serviço | 1 000,00 | 1 000,00 |
|
||||
| Recebimento parcial afectado ao documento | 400,00 | 600,00 |
|
||||
| Segundo recebimento afectado ao documento | 600,00 | 0,00 |
|
||||
|
||||
Resultado: 1 000,00 − 400,00 − 600,00 = 0,00. Cada recebimento tem identidade e afectação próprias. Repetir qualquer comando/importação ou processá-lo em concorrência não pode acrescentar outra afectação nem reduzir novamente o saldo. Mudar o conteúdo mantendo a mesma chave de repetição deve produzir conflito.
|
||||
|
||||
### Variante de correcção redutora
|
||||
|
||||
Reiniciar o cenário apenas com fixtures de teste próprias, sem alterar o caso principal nem a factura original. Ensaiar uma redução de 100,00 numa linha do documento, identificando documento e linha de origem, identidade da correcção, montante, data, autor e motivo sintético.
|
||||
|
||||
| Acontecimento | Valor do teste | Saldo aritmético por receber |
|
||||
| --- | ---: | ---: |
|
||||
| Documento original preservado | 1 000,00 | 1 000,00 |
|
||||
| Primeiro recebimento | 400,00 | 600,00 |
|
||||
| Correcção redutora independente | 100,00 | 500,00 |
|
||||
| Segundo recebimento | 500,00 | 0,00 |
|
||||
|
||||
Resultado: 1 000,00 − 100,00 − 400,00 − 500,00 = 0,00. A correcção não apaga nem altera silenciosamente o original. A forma documental legal da correcção permanece por validar.
|
||||
|
||||
Este cenário distingue três provas: saldo operacional explicado, contabilização válida e fecho válido. A primeira não demonstra automaticamente as outras duas. Um perfil artificial de cálculo/contabilização, se aprovado para ensaio, será exclusivo de testes, identificado como sintético e impossibilitado de activar regras reais em desenvolvimento.
|
||||
|
||||
### Reconciliação exclusivamente simulada
|
||||
|
||||
Comparar os dois recebimentos/afectações com duas observações de fonte sintética, identificadas como simulação e contendo identificador, documento de referência, moeda, montante, data e estado de teste. Uma observação repetida não cria outro recebimento. Demonstrar correspondência individual e total, além de uma variante com divergência que permanece pendente.
|
||||
|
||||
Não consultar bancos, iniciar pagamentos, transferir fundos, executar débitos ou apresentar observações artificiais como extractos reais. A prova demonstra o mecanismo e os controlos incluídos, não integração ou liquidação bancária real.
|
||||
|
||||
## Significado de fecho neste cenário
|
||||
|
||||
Fecho significa o encerramento controlado de um período contabilístico de teste, com evidência preservada. Não significa apenas terminar o formulário, marcar a prestação como concluída ou obter saldo por receber igual a zero. Não é submissão fiscal ou bancária.
|
||||
|
||||
O fecho proposto deve:
|
||||
|
||||
1. Identificar empresa, período, corte e versões de regras/dados consideradas.
|
||||
2. Verificar que os acontecimentos elegíveis foram capturados, processados e ligados aos documentos/afectações, sem efeitos perdidos ou repetidos.
|
||||
3. Conferir o sub-razão, a reconciliação simulada e os lançamentos necessários, com débitos/créditos e saldos explicáveis sob um perfil de teste explicitamente aprovado.
|
||||
4. Recusar encerramento integral se houver pendência material, divergência, classificação em falta ou configuração insuficiente. Mostrar o motivo sem inventar uma conta/regra.
|
||||
5. Preservar evidências e actor responsável, passar de aberto para em fecho/encerrado conforme validações e impedir gravações concorrentes no período encerrado.
|
||||
|
||||
Eventos tardios ou correcções posteriores não reabrem nem reescrevem o período automaticamente. O tratamento deve ser uma operação autorizada segundo política ainda por validar. Sem perfil contabilístico suficientemente definido, a prova esperada é a recusa fundamentada do fecho; não uma conclusão artificial de conformidade.
|
||||
|
||||
## Dados mínimos propostos
|
||||
|
||||
| Entidade | Dados e vínculos iniciais |
|
||||
| --- | --- |
|
||||
| Contraparte com papel de cliente | Identificador estável, empresa, nome e papel de cliente; não duplicar o futuro cadastro de fornecedor |
|
||||
| Serviço | Identificador, empresa, nome e descrição; sem preço comercial ou regra fiscal por omissão |
|
||||
| Prestação | Empresa, unidade, cliente, linhas de serviço, descrição, quantidade, data da prestação e estado |
|
||||
| Rascunho de facturação | Origem da prestação, cliente, empresa/unidade, moeda, linhas, preços propostos, versões e pendências |
|
||||
| Documento confirmado futuro | Identidade própria e fotografia dos dados/regras efectivamente aplicados; numeração e validade dependem de decisão |
|
||||
| Recebimento futuro | Identidade, empresa, cliente, data, moeda, montante, origem/evidência, estado e afectações aos documentos |
|
||||
| Correcção futura | Referência ao original, linhas/valores abrangidos, motivo, autor e efeitos aprovados |
|
||||
| Evento durável | Identidade, origem/versionamento, empresa/unidade, instante, tipo, correlação e processamento |
|
||||
| Pendência contabilística | Evento, informação/regra em falta, estado, motivo e historial de resolução |
|
||||
|
||||
Não acrescentar já contratos recorrentes, horas, equipas de projecto, custos, campos fiscais presumidos ou stock. A moeda funcional, precisão e regras de cálculo da empresa não são inferidas do exemplo de teste.
|
||||
|
||||
Identificadores de tenant, empresa e unidade vêm do contexto autorizado. Cliente e serviço devem pertencer à empresa da prestação. Uma escolha de cliente reutiliza o cadastro; documentos confirmados futuros preservam a fotografia histórica necessária em vez de dependerem do cadastro mutável.
|
||||
|
||||
## Estados propostos
|
||||
|
||||
- Prestação: rascunho, confirmada ou cancelada antes de confirmação. Uma correcção posterior referencia a prestação confirmada; não elimina a origem.
|
||||
- Facturação: rascunho, com pendências, pronta para validação e confirmada apenas com regras/configuração suficientes. Guardar um rascunho não equivale a emitir factura.
|
||||
- Cobrança: sem afectação, parcialmente recebida ou saldo liquidado, derivados dos montantes e estados admissíveis, não de um botão livre.
|
||||
- Recebimento: registado, com evidência por verificar, conciliado ou corrigido por operação rastreável. Os critérios concretos de evidência e liquidação serão aprovados.
|
||||
- Contabilidade: capturado, pendente, pronto, contabilizado ou sem efeito justificado. Falha técnica fica distinguida de informação em falta.
|
||||
- Período: aberto, em fecho ou encerrado, sujeito à política a validar.
|
||||
|
||||
O primeiro incremento não deve apresentar os estados futuros como capacidades já entregues.
|
||||
|
||||
## Regras técnicas propostas
|
||||
|
||||
1. Guardar preços, quantidades e montantes com precisão controlada; usar brick/math existente no servidor e cadeias decimais nas APIs. Não usar o JavaScript como autoridade financeira.
|
||||
2. Validar escala e arredondamento explicitamente. A política financeira/fiscal precisa de aprovação; não depender de coerção silenciosa da base.
|
||||
3. Negar por omissão cada acção e verificar empresa, unidade, registo e permissão no servidor. As concessões actuais de identidade não concedem acesso automático às novas áreas.
|
||||
4. Recusar um formulário com contexto ou versão desactualizados. Mudança de empresa/unidade não relocaliza registos nem reaproveita silenciosamente autorizações anteriores.
|
||||
5. Usar chaves de idempotência por empresa/operação/conteúdo para comandos repetíveis. Repetição idêntica recupera o resultado; conteúdo diferente com a mesma chave origina conflito.
|
||||
6. Confirmar alteração, evento durável e trabalho pendente na mesma transacção. A outbox é uma proposta técnica a implementar no núcleo, sem exigir Redis ou novo fornecedor.
|
||||
7. Não duplicar efeitos contabilísticos quando um evento é repetido ou uma interface comercial é activada posteriormente.
|
||||
8. Sem plano de contas, classificação, imposto, moeda ou reconhecimento aprovados, criar pendências explícitas. Não escolher contas transitórias para ocultar lacunas.
|
||||
9. Manter auditoria das alterações relevantes, sem palavras-passe, tokens ou raciocínio interno da IA.
|
||||
10. Fecho verifica eventos, pendências, reconciliação e integridade, incluindo concorrência. Um saldo operacional nulo não basta para fechar.
|
||||
|
||||
## Ecrãs propostos
|
||||
|
||||
Reutilizar a navegação e o cabeçalho de contexto existentes:
|
||||
|
||||
- Clientes: pesquisar, consultar e preparar o cadastro mínimo de contraparte com papel de cliente.
|
||||
- Serviços: pesquisar e manter o catálogo mínimo.
|
||||
- Prestações: lista, detalhe e formulário com cliente, serviço e origem reutilizados.
|
||||
- Facturação: rascunho ligado à prestação, valores e pendências visíveis; sem aparência de documento fiscal emitido.
|
||||
- Detalhe do percurso: linha do tempo de prestação, documentos, recebimentos, correcções e pendências, conforme cada entrega disponibilizada.
|
||||
- Posteriormente, recebimentos/reconciliação e fecho, depois de aprovadas as regras respectivas.
|
||||
|
||||
As interfaces mostram o que está guardado, o que falta e a próxima acção permitida. Não disponibilizar operações de servidor ainda inexistentes através de botões simulados.
|
||||
|
||||
## Permissões propostas
|
||||
|
||||
Separar consulta e alteração de cadastros, criação/edição/confirmação de prestações, preparação/confirmação de documentos, registo/afectação/correcção de recebimentos, reconciliação e fecho.
|
||||
|
||||
As concessões serão dados parametrizados, mas o catálogo cobre apenas acções suportadas. Gestão de acessos não implica capacidade financeira. Não ampliar automaticamente os direitos de Osmane ou Samira. A matriz concreta e a autoridade inicial de concessão das novas acções precisam de aprovação antes da disponibilização.
|
||||
|
||||
## Entregas verificáveis
|
||||
|
||||
### A Cadastros e preparação operacional
|
||||
|
||||
Proposta para a primeira implementação:
|
||||
|
||||
- Contraparte/cliente e serviço mínimos.
|
||||
- Prestação em rascunho, reutilizando esses cadastros e o contexto existente.
|
||||
- Rascunho de facturação ligado à prestação, sem emissão fiscal ou numeração definitiva.
|
||||
- Captura durável dos acontecimentos abrangidos e pendências explícitas de classificação, sem inventar lançamentos.
|
||||
- Permissões, auditoria, controlo de versão/contexto e repetição segura desde estes primeiros comandos.
|
||||
- Dados sintéticos e provas apenas na base de testes; nenhuma factura ou recebimento real em desenvolvimento.
|
||||
|
||||
Critério: percurso cliente → serviço → prestação → rascunho reproduzível, com origem preservada, acessos indevidos recusados e informação insuficiente assinalada. Isto não é ainda o circuito financeiro completo.
|
||||
|
||||
### B Documentos e contabilidade permanente
|
||||
|
||||
Após validar campos/regras aplicáveis: confirmação documental, fotografia histórica, eventos/outbox, consumidor repetível, regras de contabilização e pendências. Demonstrar contabilidade permanente mesmo sem interface comercial de Contabilidade contratada.
|
||||
|
||||
### C Recebimentos correcção reconciliação e fecho
|
||||
|
||||
Completar o cenário sintético, incluindo os dois recebimentos, correcção ligada ao original, reconciliação explicável e tentativas de fecho com e sem pendências. Demonstrar concorrência, interrupções e recuperação. Utilização real fica dependente de regras e responsáveis aprovados.
|
||||
|
||||
Demonstrar separadamente o caso principal (400,00 + 600,00 liquidam 1 000,00) e a variante de correcção (400,00 + 500,00 liquidam o saldo líquido de 900,00). A reconciliação é sempre identificada como simulada.
|
||||
|
||||
Estas entregas partilham o mesmo núcleo. Não criam três produtos ou versões divergentes.
|
||||
|
||||
## Critérios de aceitação
|
||||
|
||||
- Cliente/serviço de outra empresa ou unidade não autorizada recusados por URL/API, identificador manipulado ou tarefa.
|
||||
- Utilizador de consulta não consegue alterar, confirmar, receber, corrigir ou fechar.
|
||||
- Direitos revogados e contexto alterado produzem recusa no pedido seguinte.
|
||||
- Um cliente e uma prestação são reutilizados na facturação sem recaptura ou duplicação de cadastros.
|
||||
- Guardar rascunho, repetir comando e retomar depois de falha não duplica documentos/eventos.
|
||||
- Documento confirmado futuro conserva dados e regras mesmo que o cadastro seja alterado.
|
||||
- Os valores do cenário e todas as afectações são explicáveis pelas origens e calculados com decimais controlados.
|
||||
- Falta de regra fiscal/contabilística gera pendência, não taxa zero, conta inventada ou estado contabilizado.
|
||||
- Correcção conserva o original, motivo e vínculos, sem edição directa de lançamentos confirmados.
|
||||
- Falhas antes/depois do commit e dois consumidores concorrentes não deixam efeitos parciais ou duplicados.
|
||||
- Fecho com lacuna material é recusado; lançamento concorrente não ultrapassa período encerrado.
|
||||
- Activação posterior de interface de Contabilidade não repete efeitos já produzidos.
|
||||
- Testes destrutivos continuam restritos a sgf_tempo_test e fixtures não entram como operações da Tempo Lda.
|
||||
|
||||
## Decisões pendentes antes das entregas correspondentes
|
||||
|
||||
Para A: aprovar esta delimitação e a matriz de permissões/autoridade inicial; confirmar quais dados mínimos do cliente são indispensáveis para um rascunho (a proposta inicial exige apenas nome).
|
||||
|
||||
Para B/C: responsáveis de validação contabilística/fiscal, documentos e numeração, regime/impostos aplicáveis, moeda funcional, plano de contas, reconhecimento, arredondamento, evidências de recebimento/reconciliação, corte e regras de fecho/correcção. O exemplo de teste não decide estas matérias.
|
||||
|
||||
Não seleccionar fornecedor, API bancária ou integração de pagamento. Não construir agora plano comercial, motor geral de parâmetros, IA, sincronização offline ou toda a orquestração Camaleão. As lacunas não justificam codificar valores de negócio fixos como substituto de validação.
|
||||
|
||||
## Estado desta etapa
|
||||
|
||||
Especificação proposta para revisão. Nenhuma migração, cadastro, documento, evento financeiro ou lançamento foi criado nesta etapa. O incremento de identidade está aceite e concluído; qualquer implementação posterior exige autorização sobre uma entrega concreta. O utilizador manteve expressamente serviços apenas em especificação e não autorizou implementação financeira ou publicação. Não implementar a entrega A nesta revisão documental.
|
||||
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 54 KiB |
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"environment": "sgf_tempo_test, browser-testing, localhost:8001",
|
||||
"results": [
|
||||
"CSRF: pedido de alteração sem token/origem válida recusado (419).",
|
||||
"URLs/API: empresa do mesmo tenant e unidade sem acesso recusadas; consulta não permite edição (403).",
|
||||
"Concessão e revogação: efeito no pedido seguinte em sessão independente (200 → 403).",
|
||||
"Formulário anterior à mudança de contexto recusado (409).",
|
||||
"Gestor limitado não consegue conceder edição que não possui (403).",
|
||||
"Replay do cookie da sessão terminada recusado (401)."
|
||||
]
|
||||
}
|
||||