11 KiB
SGF — primeira ligação funcional de consulta de Stock
Continuação posterior: API de consulta ligada às duas aplicações. A pendência da segunda composição de consulta ficou coberta no recorte sintético de API; a página nativa Compras, a demonstração persistente e os escritores/recepção/consumo continuam separados. Os resultados abaixo conservam as fontes e condições da primeira entrega.
02/11/2026. SGF-STOCK-READ-SIM-v1, entrega parcial sintética do âmbito preparado. Existe agora código funcional de consulta comum e adaptador/interface SGF. Não estão entregues as operações de stock, a ligação oficina/recepção nem a segunda composição HTTP de Compras. Não se declara o módulo integral concluído.
O que ficou implementado
- Pacote
packages/inventory-read: projecção de leitura do modelo de artigos, armazéns e livro físico existente em Compras. Sem copiarStockWorkflow, novo escritor de movimentos ou tabela de saldos concorrente. GET /api/stock-read, pertencente ao módulo Stock: artigos, armazéns, existências físicas por par e movimentos, com pesquisa, filtro por armazém e páginas de 25/100. Ordenação e totais calculados no SQL; sem carregar catálogos/livro completos no PHP ou consulta por linha.- Interface de consulta em Stock → Existências, apenas quando a identidade tem
stock.viewna unidade. A consulta apresenta os quatro percursos, pesquisa, páginas, origem/referência de movimento, unidade exacta e referência de leitura. Os restantes ecrãs continuam informativos; não surgem comandos de entrada/saída. - Fonte ausente/incompatível devolve indisponibilidade explícita (503), sem transformar ausência em saldo zero. Reservado, bloqueado, disponível e valorização não são inferidos. Só se apresentam pares com movimentos elegíveis; artigo sem movimentos continua consultável no catálogo.
Estado de ligação: a fonte operacional está vazia por omissão. O adaptador admite exclusivamente APP_ENV=testing, guarda física de base QA e schemas sintéticos próprios; não liga à pasta/base Compras em runtime. As fixtures reproduzem o recorte de leitura do schema de origem. Isso permite desenvolver o leitor e o consumidor SGF sem alterar o escritor existente, mas não comprova recepção → movimento entre as duas aplicações nem paridade entre dois hosts HTTP autenticados. A incorporação comum na composição de Compras permanece trabalho seguinte.
Isolamento, permissão e coerência
Direito proposto no âmbito: stock.view na unidade. Não concede cadastro, movimento, custo ou todos os armazéns. O adaptador exige ainda contexto/módulo Stock e token de geração actual. Cada contexto é mapeado explicitamente para tenant da fonte e lista de armazéns; os IDs da fonte não são assumidos iguais aos IDs SGF. Company view, administração ou direitos de oficina não substituem Stock.
A base tinha uma restrição SQL que ainda não reconhecia esse direito. No ensaio foi estendida apenas a restrição da base de regressão, criados grants para actores novos QA e, no final de cada teste, retirados esses grants e reposta a definição anterior. Não há migração de destino, nova concessão real ou activação em 8039. O pós-check READ ONLY confirmou zero stock.view remanescentes, restrição sem o direito e zero bindings activos fora da configuração de teste. Antes de usar noutro ambiente será preciso um incremento de schema/direitos e fonte delimitado, não simplesmente retirar a guarda testing.
Cada pedido usa transacção própria READ ONLY / REPEATABLE READ, com 3 s de limite SQL apenas nessa transacção. Não usa locks de escritor. A página e os seus totais/revisão provêm da mesma fotografia. O token cifrado vincula actor, contexto, mapeamento, filtros/tamanho de página e revisão; expira após dez minutos. Mudança de catálogo, movimentos, âmbito ou token provoca 409, exigindo consulta actualizada. Não é um arquivo histórico as-of: qualquer alteração relevante invalida a continuação. Contagem/max do livro pressupõem fonte append-only, como no modelo de origem e no trigger da fixture; não deve ser ligada uma fonte mutável sem rever o protocolo.
Quantidades são quantity_milli, somadas em SQL e devolvidas como cadeias exactas; o frontend usa BigInt, sem float. A resposta exclui o snapshot bruto, custos e documentos privados, mantendo identificador/referência segura do movimento. A proveniência documental completa/consulta do documento original permanece dependente do futuro adaptador de origem; esta leitura não a inventa.
Provas executadas e reutilizadas
Só a base sgf_tempo_test / sgf_test_runner / porta 55439 / cluster sgf_modular_regression_2576427d1939 foi usada. Guarda física conferida antes de mutações. Schemas novos sgf_stock_read_<12 hex> e identidades novas foram conservados exclusivamente na regressão; sem reset, migração dos dados antigos ou limpeza das fixtures anteriores. Os grants temporários foram removidos e a restrição reposta; não se declara rollback de toda a preparação sintética.
| Prova | Resultado |
|---|---|
| Primeira suite Stock | 3 testes / 465 asserções aprovados, incluindo carga/percurso de páginas |
| Casos funcionais finais, após tratar fonte incompatível e ampliar recusas | 2 testes / 77 asserções aprovados; substituem os dois casos anteriores, não são cobertura adicional a somar |
| Carga válida conservada dessa suite | 1 teste / 398 asserções; 24 perfis, 72 pedidos medidos; percurso integral das páginas de existências nas três escalas |
| Navegação afectada pela propriedade do endpoint | 8 testes / 90 asserções aprovados |
| Frontend | Compilação Vite aprovada; renderização estática, direitos separados e quantidades exactas aprovados |
| Pós-check e provas anteriores | Zero grants Stock temporários, restrição reposta, bindings vazios; hashes das provas da fila preservados |
Cobertura: 10−2=8 unidades físicas por artigo; duas unidades/armazéns elegíveis contra ruído restrito e de outro tenant; catálogo sem movimentos; origem/documento privado excluído; pesquisa literal %; acesso indevido; parâmetro de contexto arbitrário; POST sem rota; versão de catálogo/livro antiga; contexto antigo; revogação; fonte ausente/incompatível e recuperação. Comparação directa com o leitor comum usa a mesma fixture autorizada; não é a segunda composição de Compras.
Uma tentativa inicial foi desfeita por a restrição SQL recusar o direito novo, levando à extensão QA temporária com reposição. Na ampliação do teste, uma ordem incorrecta de pedidos deixava o cabeçalho antigo activo antes de testar validação 422; corrigiu-se o teste e repetiram-se apenas os dois casos funcionais. A matriz válida não foi repetida. A primeira tentativa SSR atingiu timeout com os plugins da aplicação; o check foi isolado da configuração de desenvolvimento e passou. A cache bloqueada não foi limpa nem usada para contornar esse resultado.
Medições novas deste leitor
Três amostras por perfil, kernel HTTP aquecido em processo, sem concorrência. N significa N artigos com movimentos, mais um artigo sem movimentos; N pares elegíveis de saldo, 2N movimentos elegíveis, dois armazéns autorizados e ruído inacessível. Não significa N armazéns. A preparação ficou fora da medição; sem experiências de índices, além das chaves primárias das tabelas QA. Os filtros e as tabelas diferem da fila de associações: estes tempos não são um antes/depois daquela optimização.
| N | Consulta | Página | Mediana ms | Consultas instrumentadas | Memória incremental máxima KiB |
|---|---|---|---|---|---|
| 1 000 | Existências | 25 | 28,570 | 15 | 79,09 |
| 1 000 | Existências | 100 | 32,412 | 15 | 197,31 |
| 5 000 | Existências | 25 | 99,207 | 15 | 79,09 |
| 5 000 | Existências | 100 | 92,208 | 15 | 197,31 |
| 10 000 | Existências | 25 | 143,295 | 15 | 79,09 |
| 10 000 | Existências | 100 | 146,565 | 15 | 197,31 |
| 1 000 | Movimentos | 25 | 27,426 | 15 | 80,78 |
| 1 000 | Movimentos | 100 | 25,314 | 15 | 207,86 |
| 5 000 | Movimentos | 25 | 96,232 | 15 | 80,78 |
| 5 000 | Movimentos | 100 | 76,294 | 15 | 207,86 |
| 10 000 | Movimentos | 25 | 122,667 | 15 | 80,78 |
| 10 000 | Movimentos | 100 | 121,913 | 15 | 207,86 |
As 15 consultas incluem sessão/contexto/permissões, controlo da transacção e leitura; o leitor faz cinco operações SQL (três de revisão/metadados, total e página), independentemente do número de linhas devolvidas. Sem N+1 observado neste recorte. Memória incremental não inclui todo o processo ou PostgreSQL. Artigos/armazéns e todas as amostras/picos/tamanhos constam da medição completa.
A revisão ainda varre/agrega metadados da fonte no SQL; contagem e soma dos movimentos também crescem com o histórico. O aumento de latência nas escalas está visível, não escondido por cache. Antes de ampliar, avaliar planos/filtros e índice específico do livro em ensaio próprio, separando esse ganho; não criar cache persistente ou saldo paralelo como atalho. Não foram medidos cauda, escritores concorrentes ou saturação.
O tratamento final de erro de fonte foi acrescentado depois da medição. O leitor e o percurso SQL de sucesso ficaram iguais; os hashes do controlador medido e final são registados separadamente no resumo, com os testes finais. Não atribuir ao ramo de falha uma medição que não foi feita.
Continuidade e limites
Próximo incremento: preparar o adaptador de consulta da composição Compras sobre este mesmo leitor, demonstrando equivalência com autenticação/contexto próprios. Depois, recepção → escritor único e, separadamente, oficina → consumo físico. A operação de movimento não será construída dentro do leitor nem executada ao consultar o saldo. Financeiro e Contabilidade conservam os seus efeitos e pendências no plano de ligações.
O código é local. Nenhum servidor/demonstração foi actualizado ou reiniciado nesta entrega; a configuração de fonte é exclusivamente de teste e não fica acessível em 8039 por consequência do código. Ficam pendentes a demonstração persistente própria, a segunda composição e a integração operacional. Não se liga esta fonte à instalação real apenas editando configuração.
Os seis registos protegidos, a cache bloqueada, alterações alheias e provas válidas foram preservados. Não se alterou Compras, activou candidata, concedeu direito público, publicou ou criou checkpoint. Revisão visual e capacidade de implantação permanecem pendentes, separadas das provas de API, renderização estática e build.
Ferramentas: scripts/stock-read-regression.mjs (suite nova), opção functional (apenas casos funcionais), scripts/stock-read-ui-check.mjs (SSR sem configuração de servidor) e scripts/stock-read-state.php (pós-check READ ONLY). Usar PHP/Node fixados e sync da cópia de regressão; não prepare/reset ou PHPUnit em demonstrações.