# B1 — confirmação interna e fotografia histórica Data: 25 de Outubro de 2026 (Africa/Johannesburg). Estado: B1 aceite pelo utilizador no âmbito demonstrado de confirmação interna, sem validade fiscal nem lançamentos contabilísticos. Não constitui conclusão integral de B. A permanece aceite no checkpoint `ca13acb`, com antecessor `26b80df`; nenhum foi substituído ou reaberto. ## Aceitação Em 25 de Outubro de 2026, o utilizador declarou: «Aceito B1 no âmbito demonstrado de confirmação interna, sem validade fiscal nem lançamentos contabilísticos. Regista a aceitação e preserva um checkpoint Git local, sem credenciais ou dados locais. Não avances para os restantes incrementos nem publiques.» O checkpoint preserva código, migração, documentação e provas sintéticas. Exclui credenciais, configurações privadas, bases, sessões e logs. As contagens de desenvolvimento neste relatório são evidência histórica da entrega, não uma cópia dos dados locais. A aceitação encerra apenas B1 e mantém os limites abaixo. ## O que ficou funcional Um utilizador com `billing_drafts.view` e a nova concessão explícita `billing_drafts.confirm_internal`, na empresa/unidade seleccionadas, pode abrir o rascunho, rever a operação e confirmar uma versão actual. A interface apresenta **«Confirmado internamente — sem validade fiscal»** e referência técnica `INT-B1-`, distinta de numeração fiscal. A confirmação exige cliente/serviços válidos na empresa, prestação na mesma unidade, versão da prestação correspondente à origem guardada, designação e linhas com quantidade positiva/preço não negativo completos. Reutiliza as validações decimais de A. Campos e identificadores protegidos enviados pelo navegador são recusados. Empresa/unidade, pertenças e permissão são revalidadas no servidor dentro da transacção, após bloquear a empresa e antes da operação. A sessão e o token de contexto existentes continuam em uso. Moeda desconhecida é conservada como `null`, com pendência explícita. Imposto permanece pendente e não é convertido em zero. Mesmo uma moeda preenchida continua sujeita a validação. A base aritmética usa decimais exactos e não se apresenta como total monetário definitivo ou fiscal; não há agregação de moedas distintas. A fotografia conserva o rascunho e a prestação com versões/dados originais, cliente e serviços com versões/dados observados, linhas e valores usados, moeda conhecida ou desconhecida, pendências, âmbito, autor e instante. Os nomes nas linhas e identificação do cliente usados na confirmação são conferidos no cadastro actual, que também fica fotografado; a versão original do rascunho continua preservada separadamente. Alterações posteriores dos cadastros ou da prestação não reescrevem a fotografia. A confirmação cria uma identidade própria, sem transformar a prestação em serviço confirmado. O rascunho de origem mantém a versão fixada e fica bloqueado para edição/eliminação. API e triggers SQL impedem actualizações em massa ou eliminação do rascunho confirmado; a fotografia tem protecção append-only. Não há reabertura, correcção ou anulação. A prestação e os cadastros continuam com o comportamento de A, preservando as suas versões. ## Captura e repetição Confirmação, fotografia, histórico, evento `b1.billing_draft.confirmed_internal`, pendências, auditoria e resultado do comando são persistidos na mesma transacção. A captura reutiliza `a_history`, `a_events`, `a_outbox`, `a_pending` e `a_commands`; os eventos de A não são reconstruídos ou alterados. O outbox permanece `captured`, sem consumidor contabilístico. A fotografia mostra `not_issued` para fiscalidade e `blocked_pending` para contabilidade. Além das pendências de A, contas/classificação e reconhecimento ficam explicitamente pendentes. Não há lançamentos, receita reconhecida ou estado contabilizado. Repetição com mesma chave/autor/conteúdo recupera o resultado. Conteúdo diferente com a mesma chave produz 409. Outra chave para o mesmo rascunho/versão recupera a confirmação existente, sem novo evento. A unicidade por rascunho e bloqueios transaccionais impedem confirmações concorrentes duplicadas. Como não há reabertura, não se confirmam versões posteriores do rascunho já fixado. Resolução futura de pendências exigirá registos/versionamento próprios, sem editar a fotografia. ## Migração e acesso aplicados O delta foi apresentado antes da aplicação. Migração aditiva `2026_10_25_040000_create_internal_confirmations`, aplicada em `sgf_tempo_test` pelas provas e depois em `sgf_tempo_dev` pelo wrapper, com proprietário separado: - Cria apenas `b_internal_confirmations`, com referência única ao rascunho, versão, âmbito composto, fotografia, autor e instante. - Acrescenta triggers de validade/imutabilidade e bloqueio do rascunho confirmado; amplia a validação de `a_history` para a nova origem sem remover as origens de A. - Acrescenta `billing_drafts.confirm_internal` ao catálogo SQL permitido, sempre com unidade explícita. Não concede esse direito pela migração, por nome/email ou por direitos de A. - Não modifica dados históricos de A nem cria tabelas de lançamentos, numeração fiscal ou processamento contabilístico. O rollback automático desta migração é recusado para não eliminar confirmações históricas; qualquer reversão requer procedimento de preservação revisto. A conta existente foi conferida e apresentada: ID 1, Osmane Nala, na empresa Tempo Lda ID 1 / SEGI ID 1. O utilizador confirmou exactamente a nova concessão antes da aplicação. Foi aplicada **uma** concessão `billing_drafts.confirm_internal`, com auditoria `b1.access.initial_grant`. Samira mantém apenas consulta; os restantes direitos de A foram preservados. Total de concessões em desenvolvimento: 29. Não foram criadas contas, nem poderes de gestão da nova concessão, emissão, contabilização, recebimento ou fecho. O procedimento local `scripts/b1-access.php user_id company_id unit_id` permite pré-visualizar a conta/âmbito. `--apply` só deve ser usado depois de confirmação específica da operação apresentada. Não o executar como seed ou criação automática de direitos. A interface de gestão de A não permite delegar `confirm_internal`; alterações futuras desta concessão continuam a exigir procedimento local autorizado e auditado. `scripts/b1-status.php` verifica contagens e a concessão sem mostrar credenciais. Depois da aplicação: duas contas, um tenant, uma empresa e uma unidade preservados; clientes, serviços, prestações, rascunhos e confirmações em desenvolvimento continuavam vazios. Não foi criado qualquer documento interno real ou de demonstração na Tempo Lda/SEGI. A aplicação normal conserva `sgf_dev_app`, sem administração PostgreSQL, e a ligação à base de desenvolvimento. ## Provas realizadas Suite completa: **58 testes / 442 asserções aprovados**, incluindo regressões de identidade e A, sem reabrir a sua aceitação. Compilação Vite aprovada, sem alteração de versões, manifests ou lockfiles. Os 14 testes de B1 cobrem confirmação autorizada; consulta e gestor de A sem nova permissão recusados; revogação efectiva no pedido seguinte da mesma sessão; impossibilidade de delegar o novo direito pela gestão de A; âmbito manipulado; acesso cruzado entre unidades e entre empresas do mesmo tenant; versão/contexto antigos; fotografia preservada após alterações de cliente, serviço e prestação; moeda/regra desconhecidas; linhas incompletas; origem desactualizada; repetição/conflito; bloqueio API e SQL de edição/eliminação; fotografia append-only; falha injectada no outbox com rollback integral, incluindo auditoria e comando. Prova de concorrência com **dois processos PHP reais**, sobre PostgreSQL e com sobreposição demonstrada de bloqueios: chaves iguais e chaves diferentes produziram apenas uma confirmação e um evento por rascunho. [Resultado](proofs/b1-concurrency.json). Prova HTTP com autenticação real de contas sintéticas, CSRF activo e sessões distintas: confirmação autorizada, leitor recusado 403, contexto/versão antigos 409, repetição recuperada, conteúdo diferente 409, alteração de rascunho confirmado 409 e fotografia inalterada após edição dos cadastros. [Resultado](proofs/b1-http-results.json). No navegador isolado em http://127.0.0.1:8001, ligado exclusivamente a `sgf_tempo_test`, o gestor entrou pelo formulário, preparou um rascunho e confirmou-o pela revisão explícita. A interface mostrou moeda desconhecida, referência interna, fotografia e pendências. Após saída, a conta de consulta entrou pelo formulário e consultou a fotografia sem botões de criação, edição, gestão ou confirmação. Não foi apenas uma prova com `actingAs`. Provas visuais: [confirmação interna e pendências](proofs/b1-01-internal-confirmation.png) e [consulta com contexto sintético](proofs/b1-02-read-only-context.png). [Métricas de captura](proofs/b1-capture.json) verificam correspondência entre confirmações, históricos, eventos e outbox. A instância de prova foi parada; a suite final limpa os dados sintéticos apenas na base de testes. Não se alterou a ligação da aplicação normal, não se terminaram processos de outros projectos e não se publicaram conteúdos. ## Ficheiros e comandos Novo workflow `app/Modules/Services/InternalConfirmation.php`, integração em `ServiceController.php`, `ServiceWorkflow.php`, `routes/web.php`, `ServicesWorkspace.jsx` e rodapé de `app.jsx`; migração indicada acima. A integração acrescenta estado de confirmação à lista, protege o rascunho e evita pendências posteriores de origem reescreverem a captura já confirmada. Testes em `tests/Feature/InternalConfirmationTest.php`, fixture `tests/Support/InternalConfirmationFixture.php`; preparação de navegador adaptada e worker de concorrência existente reutilizado. Scripts próprios: `b1-access.php`, `b1-status.php`, `b1-concurrency-proof.php`, `b1-http-proof.mjs` e `b1-proof-metrics.php`. Documentação actualizada em AGENTS, README e especificações, respeitando as alterações posteriores a A. ```powershell powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\sgf.ps1 test powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\sgf.ps1 npm run build powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\sgf.ps1 php scripts/b1-status.php ``` Os scripts de concorrência/métricas verificam explicitamente o destino `sgf_tempo_test`. Parar a instância de navegador antes de executar testes que recriam essa base. Recuperação de acesso mantém o procedimento assistido de IDENTITY_WORKFLOW.md, sem fornecedor ou recuperação por email. ## Limites remanescentes B1 fixa dados internos; não emite documento comercial/fiscal, não imprime/exporta uma factura, não confirma execução do serviço, não reconhece receita nem produz lançamentos. Não foi criado consumidor contabilístico. Contas, reconhecimento, moeda funcional, regras fiscais e arredondamento fiscal continuam por validar. Não foram implementados recebimentos, reconciliação, fecho, reabertura, correcção ou anulação. O restante B e C dependem de âmbito e autorização próprios. B1 foi aceite com estes limites; A permanece encerrada. Não avançar para os restantes incrementos nem publicar.