# Stock comum — consulta ligada às duas aplicações Continuação posterior: [recepção aceite → movimento comum → consulta do mesmo livro pelo SGF](STOCK_RECEIPT_LINK_DELIVERY.md). Ficou comprovado o recorte nativo de recepção/escrita e observação SGF em QA; a preparação/confirmação de recepções na composição ERP SGF e o consumo da oficina continuam pendentes. As provas desta consulta abaixo conservam o âmbito original. 02/11/2026. `COMMON-STOCK-READ-COMPOSITION-SIM-v1`, continuação funcional da [consulta SGF](STOCK_READ_DELIVERY.md). **As APIs SGF e Compras foram ligadas ao mesmo leitor e ao mesmo protocolo de leitura**, com prova de equivalência no kernel HTTP real de cada aplicação e autorização própria. Não se declara integração operacional de recepções, consumo de oficina, contabilidade ou implantação real. ## Código e composição `packages/inventory-read/src/InventoryReader.php` mantém exactamente o hash da entrega anterior e continua a ser a única implementação da consulta. O protocolo de transacção READ ONLY / REPEATABLE READ, referência cifrada de dez minutos e recusa por mudança foi extraído do controlador SGF para `InventoryReadSession.php`, no mesmo pacote. O adaptador SGF delega nesse protocolo; não se criou outra consulta ou versão de saldo para Compras. Compras recebeu `CommonStockReadController` e `GET /api/stock-read`, dentro do grupo existente de autenticação, organização, empresa configurada e contexto de trabalho. O adaptador recarrega o actor e reutiliza as funções nativas Admin/Armazém/Procurement/Finanças da consulta de Stock; revalida perfis configurados, recusa manutenção e exige mapeamento explícito dos armazéns por tenant/actor. **Não foram criados direitos funcionais novos em Compras.** A origem não pode indicar outro tenant. Não se identificam contas ou empresas entre aplicações por nomes ou IDs coincidentes. Cada aplicação tem bindings vazios por omissão e guardas QA próprias. O SGF mantém `stock.view` na unidade e token de contexto/módulo. Compras admite esta ligação experimental apenas em `testing`, numa base `stock_read_compras_<12 hex>`, role própria correspondente, porta 55439 e cluster de regressão conferido. Não foi aberto o percurso real pela remoção de guardas. ## Uma fonte de código e artefacto verificável Fonte canónica: `sgf-tempo/packages/inventory-read`. Distribuição local para Compras: `packages/inventory-read/releases/0.1.0`, com três ficheiros e manifesto imutável. A cópia é um artefacto do mesmo código, não um segundo motor mantido separadamente. `scripts/package-inventory-read.mjs` recusa substituir uma versão com conteúdo diferente. Manifesto SHA-256: **bbd97f63b0eeb671bd3ad57bbd62bd34fcf67b8e943320423715d514a2a2c19c**. Compras verifica o hash esperado do manifesto e os hashes dos três ficheiros antes de carregar o pacote local. A prova também compara todos com a fonte canónica. O pacote de Compras não aponta para a pasta SGF em runtime; não há consulta remota ou leitura cruzada de bases. A versão 0.1.0 deste leitor **não é uma versão/candidata de Purchasing**; o apontador de Compras instalado não foi alterado. ## Provas executadas | Prova | Resultado | | --- | --- | | Aplicação Compras: middleware, API e autoridade nativa | **1 teste / 73 asserções** | | SGF: casos funcionais afectados pela extracção do protocolo | **2 testes / 77 asserções** | | Comparação entre as aplicações | **1 teste / 48 asserções**, **12 cenários equivalentes** | | Pós-checks | Role Compras sem superuser/criação de base/role/replicação/bypass; SGF com zero grants Stock temporários e restrição original reposta | A composição Compras arrancou numa cópia privada da aplicação real com os seus providers, rotas, modelos, autorização e middleware. Usou uma **base nova e role nova restrita**, separadas de `compras_dev`, das demonstrações e da regressão SGF. O SGF usou apenas a sua regressão isolada existente, com âmbito/actores/schema novos. Ambos no cluster QA 55439. Não se executou migração/reset de qualquer base existente. O primeiro arranque da cópia Compras falhou antes de preparar tabelas por faltar um pacote já exigido pelo seu provider. Copiaram-se para a cópia QA as dependências locais existentes de Purchasing, orçamento e Payables; retomou-se **a mesma base ainda vazia**, sem a apagar. O teste impede adoptar uma base com tabela `users` já existente. A versão do leitor foi conservada e verificada; nenhuma dependência Composer foi actualizada/instalada. Os 12 cenários comparam **hashes exactos das linhas e paginação**, excluindo tokens específicos da aplicação: quatro consultas × páginas 25/100, segunda página de existências, última página do catálogo, armazém autorizado sem movimentos e pesquisa selectiva. Fixtures equivalentes, separadas, com 100 artigos com movimentos, um sem movimentos, dois armazéns autorizados e ruído de armazém/tenant inacessível. Saldo de 10−2=8 unidades exactas por artigo. Não são cópias de dados reais. Compras verificou sessão sem actor (401), função indevida (403), armazéns fora do mapeamento (403), filtros arbitrários (422), token inválido/antigo (409), actualização após nova linha, fonte ausente/incompatível (503), recuperação e revogação/restauro de permissão num perfil configurado. O SGF verificou novamente os seus casos funcionais e recusou o token da composição Compras. Nenhum documento privado ou snapshot bruto foi devolvido. As sessões de teste são pré-autenticadas com identidades sintéticas (`actingAs`); os pedidos atravessam os kernels HTTP reais das duas aplicações. **Não se afirma que tenham sido testados login/MFA, rede, servidor HTTP implantado ou navegador.** Também não se afirma sincronização entre bases: cada instalação lê o seu livro, com a mesma implementação. ## Desempenho e preservação Não houve novas medições de carga. O SQL do leitor não mudou; as 72 leituras de 1 000/5 000/10 000 da entrega anterior permanecem válidas para a fonte e condições então medidas. A extracção foi coberta por testes funcionais/paridade. Não atribuir os tempos antigos ao middleware de Compras, que não foi medido neste incremento. Sem índices novos, alterações de UI ou repetição de build/navegador/suites alheias. Grants `stock.view` e extensão de restrição SGF foram temporários no ensaio, com reposição final; nenhum direito público/real foi concedido. A nova base Compras, as suas identidades e as fixtures SGF foram retidas como evidência sintética; não se declara rollback de toda a preparação. Segredos e o token de comparação permanecem no directório privado e não integram a [prova sanitizada](proofs/stock-read-composition-20261102.json). Os seis registos protegidos, a cache bloqueada, demos, dados/configurações anteriores, alterações alheias e provas válidas foram preservados. Sem activação de candidata, publicação, checkpoint ou aceitação presumidos. Os endpoints existentes de stock/movimentos em Compras não foram substituídos. ## Próximo ponto funcional A pendência **API de consulta da segunda composição** fica coberta neste recorte. Permanecem: ligar a página nativa de Compras à consulta comum se for esse o destino escolhido; disponibilizar demonstração persistente própria; extrair/delegar recepção → escritor único de movimentos; depois ligar consumo de material da oficina por origem/versão. A consulta não pode confirmar entradas ou diminuir stock. Reservado/bloqueado/disponível, valorização e documentos de origem completos continuam fora deste incremento. **Revisão visual e capacidade de implantação continuam pendentes e separadas.** Para repetir deliberadamente: `stock-read-composition.mjs` cria uma nova composição QA; só admite retoma de base vazia através do identificador privado. Depois `stock-read-regression.mjs cross ` compara o SGF. Não apontar estes testes a clientes ou demos. O artefacto é distribuído pelo script próprio, sem modificar o apontador de Purchasing.