0024 — Manifesto de remessa¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-09 · Decidido em: 2026-09-09
Contexto¶
O ERP rejeita filho sem pai, em silêncio e de forma terminal (1XX), e o coletor lê só
000/9XX — a linha rejeitada fica invisível para sempre. O ingest é atômico no Postgres, mas essa
atomicidade se perde na fronteira do PowerSync: linhas da mesma transação chegam ao cliente em
checkpoints diferentes.
Três formatos do mesmo defeito, todos medidos em produção em dois dias:
| pai ausente | pedido | evidência |
|---|---|---|
propriedades (cliente) |
260079421, 08-set |
120-Cliente CPF 072.508.149-07 não cadastrado. |
contratos (pedido) |
260079618, 09-set |
120-Pedido (10738.24) não cadastrado. |
estoque (produto) |
260078864, 09-set |
120-Produto para o pedido (…) não cadastrado. |
A cascata é 1:N e silenciosa: no 260079421 uma linha ausente produziu nove terminais; no log
inteiro, 53. E o coletor monta um arquivo com vários pedidos, então a completude tem de ser
avaliada por unidade de negócio, nunca pelo arquivo.
Do lado do cliente, "a linha ainda não chegou" e "a linha não existe" são indistinguíveis — logo nenhuma regra local resolve. O Integrador, no instante do apply, já sabe o conjunto exato.
Decisão¶
Declarar a unidade de entrega na origem: integracao_remessa + integracao_remessa_item, criadas na
mesma transação do apply e replicadas junto com as linhas.
- Uma remessa por grupo com dependência (≥2 linhas ligadas), não por push. Linha solta segue coletável — o manifesto acrescenta garantia, nunca remove, e é o que torna o rollout não-quebrante.
- Uma remessa viva por
(origem, chave_negocio)— invariante de banco (índice único parcialWHERE status <> 'ENTREGUE'). É o que faz o resgate fechar: o re-push reusa a travada e o re-arme a reabre, sem colisão. - Estado derivado por UMA função, chamada do apply, do soft-delete, do write-back e do re-arme.
Uma fonte só é o que impede o drift de
status,total_itens,bloqueadoeresolvido. - O re-arme é por remessa, não por tabela: alcança o pai e a remessa de cliente.
Alternativas descartadas¶
Estado 002 ("aguardando pai") na linha. Foi o primeiro desenho. Exigiria inventar um código
numa coluna compartilhada com o ERP — homologação com o dono do pAbast — e punha a elegibilidade na
linha, não na unidade. O manifesto a torna desnecessária.
Gate de FK no cliente. Cinco regras hoje, quinze no fluxo completo, cada uma escrita por quem talvez não conheça a semântica — e regra errada trava produção em silêncio. Pior: não resolve o caso da linha que ainda não chegou, que é o caso dos três incidentes. O manifesto é O(1) no cliente.
bloqueado deduzido pelo cliente. O princípio descartado era o cliente inferir dependência,
não modelar dependência. O servidor já tem o grafo; ele marca a flag e o cliente só a lê — a
precisão do gate de FK sem o acoplamento.
Consequências¶
O valor depende de três repos. Este declara; o integrador-client (.ia/003 dele) decide o que
entra no arquivo; o maxsul/powersync (.ia/002 dele) transporta; o maxsul-pied (.ia/009 dele)
reconcilia. Ordem de deploy: este repo primeiro (a V27 cria as tabelas que as sync rules
referenciam), depois powersync, cliente e pied. Qualquer ordem é segura — os três degradam para o
comportamento de hoje —, mas só esta entrega valor.
Uma janela fica aberta, e é do consumidor. Linha que chega antes da remessa dela é, para o
cliente, indistinguível de linha solta. Fecha-se com carência de 3 ciclos no integrador-client; o
servidor não tem como resolver, porque a remessa nasce na mesma transação e quem as separa é o
PowerSync.
A derivação roda no caminho quente do write-back — um PATCH por linha, cada um recalculando as remessas que a contêm. Dezenas de linhas por remessa no volume atual; medir antes de otimizar.
As tabelas levam prefixo integracao_, convenção nova neste repo: as três de controle
existentes (request, push_enviada, mensagem_m2m) não têm prefixo. Adotada de propósito — num
banco que tende a ser réplica do ERP, a fronteira precisa estar no nome. É candidato a §6: a casa não
normatiza nome de tabela auxiliar em base-espelho.
Verificação¶
Regressão dos três incidentes por número de pedido, contra Postgres real: a remessa inclui o pai em
cada um dos três casos, e o re-arme alcança o pai — que era o beco do desenho anterior. Mais a
derivação (pai bloqueia filho, folha não bloqueia irmã, soft-delete e órfão resolvem) e o contrato
do endpoint (bloqueado separando causa de colateral).