Pular para conteúdo

0018 — App compartilhado

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

Contexto

Apps específicos atuais (PIED, XLSX) são um por cliente — cada cliente ativa ganha sua instância (pied.<cliente>, excel.<cliente>). O padrão funciona porque o parceiro externo pertence ao cliente: a API PIED do cliente A não é a do cliente B; credencial, endpoint e ritmo de polling são do cliente. Replicar o app específico isola falhas e mantém o binário fino.

Sascar é diferente. O parceiro é um só — a Sascar (empresa de rastreamento de veículos). Todos os clientes que usam Sascar falam com a mesma API pública dela, com suas próprias credenciais. Replicar sascar.<cliente> = N deploys idênticos batendo na mesma API externa, N binários a versionar, N pipelines a manter, e nenhuma vantagem de isolamento — a Sascar já isola por credencial do lado dela.

O caso concreto (fluxo alvo do sascar.xadm.biz): a Plataforma de Integração de cada cliente tem o espelho dos MDF-es com chave da nota e placa. Enquanto o MDF-e está aberto, ela o envia ao app compartilhado. O app compartilhado guarda o cadastro do cliente (usuário/senha Sascar + token de retorno para a Plataforma de Integração) e faz polling na Sascar para saber quando o motorista chegou ao destino. Quando encerra, o app compartilhado devolve MDF-e encerrado à Plataforma de Integração, que atualiza o status no espelho; o cliente Java lê via PowerSync e importa no ERP. Um tipo ③ e um tipo ④ na mesma peça, para o mesmo parceiro, para N clientes.

Decisão

Nasce o papel app compartilhado na taxonomia da plataforma de integração:

  • 1 instância, N clientes — URL fixa na nuvem X-Adm (ex. sascar.xadm.biz), roteando por cliente via auth (token/tenant) na entrada de webhook e nas chamadas da Plataforma de Integração.
  • Não escreve no barramento diretamente — conversa com a Plataforma de Integração de cada cliente (bidirecional), que grava no espelho do cliente certo. Isso mantém intacta a §Fronteiras da plataforma (um dono por tabela): o app compartilhado só é dono do próprio banco de trabalho (cadastro por cliente, credenciais, log de polling).
  • Combina tipos ③+④ quando o parceiro é bidirecional (recebe da nuvem X-Adm, e a nuvem X-Adm precisa saber o que voltou). Um app compartilhado que só recebe é ③; um que só envia é ④.
  • Exceção, não default — o papel nasce quando o parceiro é global. Se o parceiro é do cliente (API PIED do cliente, ERP do cliente), volta ao <app>.<cliente> (app específico).

O detalhe operacional — endpoints, schema do banco de trabalho, formato de auth, contrato exato com a Plataforma de Integração — vive na arquitetura-alvo do integrador, não aqui (§1.9 da constituição: concreto no repo dono).

Nota de terminologia. Este papel foi nomeado "adaptador compartilhado" na primeira redação (2026-07-21) e renomeado para "app compartilhado" (2026-07-22, feedback interno) para casar com o irmão "app específico" (antes: "vertical") — a taxonomia da plataforma agora fala em apps por papel, não em jargões técnicos. O slug deste arquivo permanece 0018-adaptador-compartilhado.md para não quebrar links publicados.

Alternativas descartadas

sascar.<cliente> (app específico simples, um por cliente). Replica binário e credencial cada vez que um cliente ativa Sascar. Upgrade do app compartilhado vira N deploys. Nenhum ganho de isolamento — todos batem na mesma API externa e a Sascar isola por credencial dela. Custo sem benefício.

Rota na Plataforma de Integração (embutir Sascar no motor genérico dela). Reintroduz o erro (a) da §integracao.md — "para atualizar um cliente da Sascar, redeploya todo mundo". A plataforma existe para separar genérico de divergente; Sascar é divergente.

App compartilhado escrevendo no barramento do cliente (pulando a Plataforma de Integração). Daria dois donos à tabela-espelho de MDF-e (Plataforma de Integração + app compartilhado), quebrando a §Fronteiras. A cura era o app compartilhado virar dono de uma tabela separada, mas então a Plataforma de Integração teria que ler essa tabela para fechar o loop — reintroduz o acoplamento que a bidirecionalidade Plataforma de Integração ↔ app compartilhado já resolve com um dono só.

Consequências

  • Auth por cliente é responsabilidade do app. Como o token/tenant chega (header, JWT claim, path segment) fica em aberto na norma; o integrador prescreve na arquitetura-alvo.
  • O app compartilhado guarda credencial de terceiros. Ganha responsabilidade de secret storage por cliente — cadastro de usuário/senha Sascar por tenant, com o padrão de secret do central (Coolify env vars).
  • Dono do dado segue por cliente. O app compartilhado escreve no seu banco de trabalho (cadastro, credenciais, log); a Plataforma de Integração escreve no espelho do cliente correto quando o app compartilhado devolve o retorno. A regra da §Fronteiras (um dono por tabela) fica intacta.
  • A norma da plataforma ganha um 5º papel — o diagrama de topologia da §integracao.md agora mostra o app compartilhado como peça na coluna Nuvem X-Adm, ao lado dos apps específicos.
  • Reversível. Se um cliente da Sascar precisar de isolamento total (compliance, SLA), pode ser extraído para sascar.<cliente> sem mudar a norma — o padrão <app>.<cliente> continua disponível para o caso.