Files
SGF/docs/WORKSHOP_DIRECT_COST_DELIVERY.md
2026-10-27 13:57:09 +02:00

98 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WORKSHOP-DIRECT-COST-SIM-v1 — entrega técnica isolada
27/10/2026, Africa/Johannesburg. Implementa apenas o ensaio aprovado na secção 14 de [INDUSTRIAL_COST_ACCOUNTING_SCOPE.md](INDUSTRIAL_COST_ACCOUNTING_SCOPE.md). **Sem aceitação presumida, custeio real, publicação ou avanço para lote industrial/CIF.** Preservados `7628645`, oficinas, recebimentos, B1, motor exacto e aprovações. O commit posterior `ea9dcb3`, observado durante a execução e não criado por este procedimento, também foi preservado.
## Funcionalidade
- Reutiliza os apontamentos técnicos verificados de uma ordem por ID e versão. Não insere ou altera acontecimentos em `wo_*` ao propor/validar custos. A fotografia do cálculo preserva a composição derivada, não um segundo consumo ou tempo operacional.
- Taxas sintéticas com identificador, versão anterior explícita, origem técnica exacta, ordem/empresa/unidade, MZN, unidade e evidência. Zero expressamente indicado é válido; ausência é pendência. Não há procura automática da taxa mais recente: cada linha recebe ID e versão escolhidos ou ausência explícita. Identificadores alternativos podem coexistir e exigem escolha explícita.
- Preparador propõe taxas e cálculos; validador distinto aprova/recusa a versão exacta. Uma aprovação de cálculo incompleto valida só a composição declarada e conserva pendências, nunca a transforma em custo completo. A validação não altera decisões ou apontamentos técnicos.
- Cálculo limitado a duas origens seleccionadas: um consumo efectivo da empresa e um apontamento de trabalho efectivo. Entrega/devolução/requisição, deslocação, material do cliente, origem fora do âmbito ou não verificada são recusados. Não desconta novamente a devolução do consumo já observado.
- Aritmética `Brick\Math` exacta existente; conversão de MIN para H por divisão explícita por 60. Decimais finitos são apresentados exactamente; divisão não finita conserva fracção racional, sem impor arredondamento. Não se reutiliza a política de IVA. Entradas de taxa são cadeias decimais não negativas, até 16 algarismos inteiros/8 decimais, sem float ou notação exponencial.
- Versões novas preservam histórico. Correcção de origem/tarefa ou nova versão da taxa usada torna o cálculo desactualizado; nova versão de cálculo torna a anterior histórica. O conjunto de IDs de tempo/material da ordem também integra a dependência: acréscimos exigem revisão. Taxa de outro identificador não substitui a escolhida silenciosamente. Propostas/refusas de taxa sucessora suspendem conservadoramente o uso actual da versão anterior, sem alterar o seu histórico.
## Resultados demonstrados
| Caso | Composição | Resultado e limite |
| --- | --- | --- |
| Taxas identificadas e validadas | 2 UN × 50 + 105 MIN ÷ 60 × 100 | 100 + 175 = **275 MZN de custo directo conhecido**, nunca custo completo/margem |
| Taxa material ausente | Material pendente; 105/60 × 100 | **175 MZN conhecidos**, total seleccionado indisponível/incompleto e pendência explícita |
| Taxa material zero explícita, teste automatizado | 2 × 0 + 105/60 × 100 | 175 no perímetro directo, taxa zero distinguida de ausência |
| Divisão não finita, teste automatizado | 1 MIN ÷ 60 × 1 MZN/H | **1/60 MZN exacto**, sem truncagem ou cêntimo inventado |
Valorizado o perímetro seleccionado não significa que todos os custos da ordem estejam conhecidos. Sem salários reais, preços de venda, margens, custos indirectos, reconhecimento, stock ou valorização legal de inventário.
## Segurança, versões e recuperação
Novos direitos explícitos `direct_costs.view/prepare/validate`, sempre na unidade; não herdados de oficinas, emissão ou administração. Consulta de custos é separada do acesso técnico. Contexto, pertenças e direito específico são revalidados em cada comando e replay, inclusive dentro da transacção. Auto-aprovação é recusada mesmo com ambas as permissões. Identidades reais nunca são reconhecidas por nome/email no código funcional.
Transacção e bloqueio da empresa serializam preparação/validação/alterações técnicas; versões anteriores explícitas impedem duas sucessoras incompatíveis. A chave idempotente inclui actor/acção/contexto/conteúdo; resposta perdida recupera o ID, conteúdo diferente é conflito. Recalcular composição idêntica à última versão pode devolver o mesmo resultado, sem duplicar fotografia. Comando, auditoria, evento versionado e outbox são atómicos; falha de outbox desfaz a operação. Não há consumidor contabilístico. A outbox permanece `captured_no_accounting`.
FKs/CHECKs/triggers validam contexto, referências, verificação técnica, unidades, cadeias de versões, taxas aprovadas e separação de autores. As seis tabelas são append-only, incluindo contra UPDATE/DELETE em massa. O núcleo de composição exacta e a autorização autenticada são da aplicação; os triggers não são RLS nem substituem essas verificações. SQL administrativo é uma fronteira de confiança distinta. O bloqueio SQL de ambiente só admite `sgf_tempo_test` na porta 55432; a aplicação exige ainda ambiente isolado e `TestingDatabaseGuard` com papel `sgf_test_runner`.
## Provas e repetição
Provas: [resultados do navegador](proofs/direct-cost-browser-results.json), [275 MZN](proofs/direct-cost-275-browser.png), [175 MZN incompletos](proofs/direct-cost-partial-browser.png), [concorrência](proofs/direct-cost-concurrency.json) e [testes finais](proofs/direct-cost-tests.json).
Resultado final: **49 testes / 1 010 asserções, zero erros/falhas**, incluindo oito casos de custos directos. **Seis provas concorrentes aprovadas**. Compilação aprovada com Vite 8.3.5 e versões/dependências preservadas. Não foi necessária repetição da investigação fiscal. A instância do navegador foi parada antes da regressão final.
Percurso efectivamente realizado no Edge, `http://127.0.0.1:8001`, sessão/cache isolados e CSRF activo:
1. Preparador `gestor@example.test`: login real, Empresa Horizonte — Demonstração / Unidade Central — Demonstração → **Custos directos de teste**. Referências técnicas #4 v1 (105 MIN) e #6 v1 (2 UN) nesta execução; IDs não são fixos.
2. Propôs `TEST-TRABALHO` v1 a 100 MZN/H e `TEST-MATERIAL` v1 a 50 MZN/UN, com evidência sintética.
3. Validador `consulta@example.test`: login real distinto, mesmo contexto; validou as duas taxas. Não dispõe de formulário de preparação nem acesso técnico por consequência.
4. Preparador entrou novamente, escolheu explicitamente as duas taxas e calculou 275 MZN. Validador aprovou a versão exacta com fundamento de custo directo conhecido.
5. Preparador criou nova versão sem taxa material. Validador aprovou só os 175 MZN conhecidos com pendência. O resultado de 275 continuou preservado e identificado como histórico.
A fixture apenas criou/verificou fontes técnicas pelos comandos existentes da oficina, com relógio sintético local no processo para a autorização histórica e restaurado no fim. Não mudou relógio do sistema, ligação normal ou regras técnicas. Sete apontamentos de origem permaneceram sete após os cálculos. Palavras-passe aleatórias não são apresentadas ou versionadas.
Seis cenários com dois processos realmente sobrepostos: mesma taxa; mesma decisão; taxas sucessoras concorrentes; mesmo cálculo; cálculos concorrentes incompatíveis; cálculo novo versus aprovação antiga. Provas adicionais automatizadas: revogação no pedido seguinte/replay, identidades/contextos/versões manipulados, moedas/unidades/precisão, origem corrigida e ainda não verificada, imutabilidade SQL, recusa, falta versus zero e falha/recuperação de outbox. A regressão relevante inclui oficinas, recebimentos, B1 e guardas de testes.
Repetir exclusivamente em testes, sem instância de prova em execução durante os testes destrutivos:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/sgf.ps1 test '--filter=DirectCostsTest|WorkshopTest|ServiceReceivablesTest|InternalConfirmationTest|DatabaseSafetyTest'
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/sgf.ps1 npm run build
```
Para o navegador, preparar uma base de testes vazia sob as guardas existentes, executar `scripts/browser-proof.ps1 start` (prepara a fundação sintética), depois `sgf.ps1 php scripts/direct-cost-fixture.php --env=testing`. O preparador recusa estado preenchido e não apaga dados. Seguir o percurso acima com a credencial no manifesto local protegido. Depois do percurso, `sgf.ps1 php scripts/direct-cost-proof.php --env=testing` e `sgf.ps1 php scripts/direct-cost-concurrency.php --env=testing`. Parar com `scripts/browser-proof.ps1 stop`; não terminar processos alheios para libertar portas. Os testes finais recriam só `sgf_tempo_test`, preservando as provas em ficheiros.
## Migração proposta — NÃO aplicada em desenvolvimento
**`2026_10_27_090000_create_workshop_direct_costs.php`**, SQL `database/sql/direct-costs.sql`, destino futuro **`sgf_tempo_dev`**, apenas após confirmação específica.
Seis tabelas novas: `dc_rates`, `dc_calculations`, `dc_decisions`, `dc_commands`, `dc_events`, `dc_outbox`; FKs, índices, versões únicas, funções/triggers de integridade, ambiente e imutabilidade. Amplia o CHECK de concessões com três nomes de unidade, preservando alternativas existentes. Não concede acessos, não altera apontamentos ou tabelas de recebimentos/fiscalidade. `down()` recusa apagar história. Sem reset/fresh em desenvolvimento. Mesmo instalada futuramente, a aplicação e SQL continuam a impedir custeio operacional nessa base.
## Concessões propostas — separadas, NÃO aplicadas
Conferidas por leitura em `scripts/direct-cost-permissions-preview.php`, sem modo de aplicação. Todas ausentes na conferência de 27/10/2026. Âmbito exacto: **tenant #1 / Tempo Lda #1 / SEGI #1**.
| Conta existente | Proposta |
| --- | --- |
| Osmane Nala #1, nala@tempo.co.mz | `direct_costs.view`, `direct_costs.prepare` |
| Samira Nal #2, onala@me.com | `direct_costs.view`, `direct_costs.validate` |
São **quatro concessões propostas**, não autorização de aplicação ou activação real. Sem gestão de acessos, supervisão técnica, alteração dos apontamentos, salários, margem, stock ou emissão. Só as identidades equivalentes sintéticas receberam estes direitos nos testes. Técnico/verificador reais continuam sem concessões novas.
## Encerramento posterior por delegação
Em 27/10/2026, o utilizador autorizou o encerramento após conferência técnica do percurso e preservação de checkpoint local. Ver [registo de encerramento e limites](WORKSHOP_DIRECT_COST_ACCEPTANCE.md). As referências anteriores a ausência de aceitação presumida descrevem a entrega antes desta autorização; `090000`, quatro concessões e uso operacional real continuam por autorizar/aplicar.
## Instalação técnica especificamente autorizada — 27/10/2026
Após autorização expressa, aplicada **apenas** `2026_10_27_090000_create_workshop_direct_costs` em `sgf_tempo_dev`, por caminho explícito com `sgf_dev_owner`, separado da aplicação `sgf_dev_app`. Acrescentou-se exactamente essa entrada no registo de migrações; instalações anteriores preservadas, sem reaplicar `070000` ou `080000`.
Aplicadas e auditadas exactamente quatro concessões, todas tenant #1 / Tempo Lda #1 / SEGI #1: Osmane #1 `direct_costs.view` e `direct_costs.prepare`; Samira #2 `direct_costs.view` e `direct_costs.validate`. Nenhuma outra conta/unidade ou função técnica recebeu direitos.
O procedimento `scripts/direct-cost-dev-install.php` comparou em memória os registos das **60 tabelas preexistentes**, incluindo acessos, auditoria, oficinas, recebimentos e cálculo fiscal. Dados/acessos anteriores preservados. Os únicos novos registos são uma entrada de migração, quatro concessões e quatro eventos de auditoria. As **seis tabelas de custo continuam vazias**: nenhuma taxa, cálculo, decisão de custos ou demonstração na base normal.
As listagens de custos das duas contas continuam bloqueadas/vazias. Guarda, proposta de taxa, cálculo e decisão recusados com 403; guardas de oficinas, recebimentos e emissão real também recusadas. As funções SQL de ambiente de custos, recebimentos e oficinas recusaram `sgf_tempo_dev`. Fontes funcionais e guardas não foram alteradas. Resumo local em `storage/app/private/direct-cost-dev-install-proof.json`, excluído do Git, sem exportar conteúdos dos registos ou credenciais.
As referências anteriores a migração/concessões pendentes descrevem o estado anterior a esta autorização. Esta instalação não activa custeio operacional, não resolve pendências de conformidade e não autoriza publicação, custos indirectos ou lote industrial. O checkpoint `d10ba06` permanece preservado. Sem alteração funcional, não foram repetidos testes destrutivos, compilação ou a demonstração aceite.
## Ficheiros e limites
Núcleo `app/Modules/Workshop/DirectCosts.php`, controlador `Http/DirectCostsController.php`, interface `resources/js/DirectCostsWorkspace.jsx`, integrações em `app.jsx` e `routes/web.php`; migração/SQL acima; `tests/Feature/DirectCostsTest.php`, `tests/Support/DirectCostFixture.php`; scripts `direct-cost-fixture.php`, `direct-cost-worker.php`, `direct-cost-concurrency.php`, `direct-cost-proof.php`, `direct-cost-permissions-preview.php`; esta documentação e provas. Não se alteraram ferramentas/dependências ou o motor fiscal.
Recorte deliberado de duas origens, uma moeda e uma ordem, sem partilhas entre ordens, custos indirectos, lote, produção em curso, margens, stock ou facturação. Taxas ligadas à versão exacta da origem exigem nova taxa validada para uma correcção técnica; não há tabela universal de salários/custos. Sem PDF/exportação, assinatura digital, activação real ou aceitação presumida. As fotografias/eventos anteriores e todos os bloqueios permanecem preservados.