Preserva base local aceite de identidade e acessos

This commit is contained in:
Codex
2026-10-25 21:29:22 +02:00
commit 26b80df545
112 changed files with 13259 additions and 0 deletions
+105
View File
@@ -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.
+70
View File
@@ -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.
+56
View File
@@ -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.
+207
View File
@@ -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.
Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

+11
View File
@@ -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)."
]
}