Pular para conteúdo

PowerSync — o transporte praticado

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-07

O PowerSync é o transporte bidirecional entre o Postgres por cliente (o barramento) e as pontas. O connector vive na Plataforma de Integração; o PowerSync serve dois consumos: os apps consumidor Web e Mobile (saída X-Adm→app) e o cliente Java do ERP (entrada nuvem→ERP). Apps específicos que enviam para fora (tipo ④) NÃO consomem PowerSync — o transporte com a Plataforma de Integração é REST. Esta página é só o praticado — o padrão provado nos pilotos, não o aspiracional.

Norma × detalhe

A norma de integração está na constituição §8 e o desenho em Plataforma de Integração. Aqui, a tech.

Cliente (a face do app)

  • Sync read-only por padrão. O app lê o SQLite local que o PowerSync mantém; não escreve direto no Postgres.
  • Write-back só via uploadData. Campo editável (ex. nome-curto no navarro_app) sobe pelo uploadData do connector → POST na Plataforma de Integração, que grava nas tabelas que ela possui. O app nunca fala com o banco; a autoridade da escrita é do dono da tabela (owner-writes, §8).

Connector (server-side, na Plataforma de Integração)

  • Dono do write-back. O connector aplica os write-backs dos apps nas tabelas da Plataforma de Integração (a réplica).
  • Campo de app nunca é sobrescrito pelo ERP. O push do X-Adm reidrata a réplica; os campos que o app edita (nome-curto, status) são preservados — o apply do push não pisa neles. É invariante: dois donos lógicos na mesma linha (o ERP e o app) exigem que o merge respeite a coluna de cada um.

Auth (o consumidor decide o modo)

Duas classes de consumidor, dois modos — quem tem usuário vs quem é máquina:

  • App com usuário real — o PowerSync valida o JWT do usuário pelo JWKS do auth.xadm.biz (ou pelo jwks_uri do Google, nos apps que autenticam por Firebase).
  • Cliente máquina-a-máquina (o cliente Java do ERP na entrada — sem humano) — nasce self-signed + JWK inline: o cliente assina o próprio JWT com uma key privada em env e o PowerSync valida contra o JWK público inline na config. É o mais simples e não acrescenta peça (sem broker, sem IdP) — reserve Firebase/pAbast para quem tem usuário de verdade. A key privada é segredo de env (nunca em repo/log) e o algoritmo é público — é Kerckhoffs, não fórmula-em-claro. Cuide do kid/audience na config para o PowerSync casar o JWK certo. (Não confunda com o M2M do broker de setup, que emite token de serviço — lá quem assina é o auth, aqui é o próprio cliente.)
  • JWKS inline > jwks_uri — vale para os dois modos. Preferir a chave inline na config do PowerSync a apontar um jwks_uri: a busca remota tem timeout de ~3s e sofre com NAT hairpin (o container batendo no próprio domínio público via Traefik) → falha intermitente de auth (recorrente em produção, em mais de um cliente). Inline elimina a ida à rede — e o self-sign do M2M já nasce inline por construção. Exceção: o Firebase usa o jwks_uri do Google (chaves rotativas, sem inline) — a regra inline vale para JWK próprio (auth ou self-sign), não para o do Google.

Config (as pegadinhas)

  • edition: 3 é obrigatório no sync_config. Sem ele, o PowerSync cai num fallback legacy silencioso — funciona no happy-path e diverge sutilmente depois, sem erro visível. Fixe a edição.
  • Callback sempre-200. O endpoint de upload/callback (write-back uploadData) responde HTTP 200 com o resultado no corpo (sucesso/erro), nunca um não-2xx para erro de negócio — senão a fila do cliente trava e reenvia em loop. É o mesmo contrato do push do X-Adm (erro vai no corpo, não no status). Este é o caso que exige o 200-sempre no status-por-caso do contrato app↔app: onde há PowerSync ou fila no meio, 200 é obrigatório e não muda; par app↔app novo sem fila usa status HTTP real.

Deploy (verificar antes do release)

O PowerSync self-hosted é uma stack Docker Compose (imagem journeyapps/powersync-service pull, config + sync rules em volume). docker build não o exercita — sem Dockerfile próprio, não há o que buildar; bootstrap (load de sync rules, migração) e healthcheck só rodam no up, e o primeiro a subir a stack de verdade é o Coolify, em produção. Antes de taggar, suba a stack efêmera com volume novo e espere os healthchecks — a /xadm-release faz isso no pré-flight (bloco Docker Compose em Particularidades): docker compose -p <slug>-preflight up -d --wait + down -v. --wait reprova se um serviço fica unhealthy ou um container de bootstrap sai ≠0.

Servidor-consumidor (ponteiro)

Consumir PowerSync em Java (hoje: o cliente do ERP na entrada) exige uma bridge Kotlin (PsBridge.kt, ~190 linhas). A base de consumo (idempotência + tabela de status) e o desenho de cada tipo de fluxo vivem em Plataforma de Integração e, no concreto, na arquitetura-alvo do integrador. De olho no repo do PowerSync: uma API Java pura deve eliminar a bridge.