Starter pack
Você entrou na squad de Operações da Karhub como dev backend Go. Esta página é o ponto de partida: o que a empresa faz, por que o sistema é do jeito que é, e em que ordem ler o resto do site.
Leia esta página inteira antes de abrir código. Ela leva uns 15 minutos e economiza semanas.
O que é a Karhub
A Karhub vende autopeças pela internet. Os canais são o Mercado Livre e a loja própria (Shopify). O cliente final é quem está com o carro quebrado, ou a oficina que vai consertar.
Até aí é e-commerce comum. O que muda tudo é o modelo:
A Karhub quase nunca tem a peça em estoque quando a venda acontece. A gente vende primeiro e compra depois — em horas.
O catálogo tem ordem de centenas de milhares de SKUs. Estocar isso é inviável: autopeça é item de baixo giro e alta variedade — cada modelo de carro, cada ano, cada montadora. Então a Karhub anuncia o que os fornecedores (distribuidores de autopeças) têm, e só compra de verdade depois que o cliente comprou de nós.
As três consequências
Praticamente toda regra estranha do sistema sai daqui:
| Consequência | Por quê |
|---|---|
| O prazo manda em tudo | Entre a venda e o despacho existe um ciclo inteiro de compra. O prazo de expedição ordena qual compra é urgente e qual venda leva a peça que acabou de chegar no CD. |
| O fornecedor faz parte do produto | Preço, disponibilidade e prazo mudam por fornecedor. Escolher de quem comprar é uma decisão de sistema, não de cadastro. |
| Tudo é por CD | A Karhub opera mais de um centro de distribuição. Estoque, demanda, compra e conferência são por CD. Uma venda do CD 1 não é atendida por peça do CD 2. |
E o sistema que a gente escreve é, no fundo, a máquina que fecha esse ciclo rápido o bastante para o prazo do marketplace.
O ciclo, em uma tela
CATÁLOGO VENDA COMPRA RECEBIMENTO SAÍDA
──────── ───── ────── ─────────── ─────
sku ──► ad ──► anúncio cliente compra recomendação chega a NF-e nota de saída
│ │ no ML/site order + order_item purchase_order o operador bipa etiqueta
│ └─ cd_id prazo de expedição pedido ao estoque + alocação despacho
└─ sku_supplier fornecedor libera a venda bip de embarque
(de quem, a quanto)
Onde cada etapa vive no código:
| Etapa | Serviço | Escreve em |
|---|---|---|
| Venda entra (Mercado Livre) | ml-webhook-adapter | cerbero.webhook_notifications → Pub/Sub |
| Venda entra (Shopify/Yampi) | shopify-webhook-adapter | idem |
| Pedido persistido | order-processor | cerbero.order, order_item, expedition |
| O que comprar e de quem | purchase-recommendation | cerbero.purchase_recommendation |
| Fechar e mandar ao fornecedor | purchase-closing | cerbero.purchase_order* |
| NF-e de entrada e conferência | supplier-invoice-receiving | cerbero.supplier_invoice*, conference_scan |
| Estoque e alocação | wms-service | alocação, espelho Omie |
| Telas da operação | compras-web | — |
O catálogo (sku, ad, supplier, sku_supplier) não é escrito por nenhum serviço do
Cerbero: é de outros times e a gente só lê. Isso é importante e está detalhado em
O catálogo.
Essa tabela cobre a nossa camada. A Karhub inteira tem ~47 repositórios e ~530 mil linhas — catálogo, preço, anúncios em cinco canais, busca, pós-venda — e o legado em Node ainda é o maior bloco de código, rodando em produção.
O mapa completo de quem faz o que e como está em O ecossistema Karhub. Os números — filas, tópicos, tabelas, testes — em A dimensão da Karhub.
Você não precisa disso no dia 1. Precisa no dia em que alguém citar turboads, tanque-cheio ou
auto-purchase-order numa reunião — o que acontece na primeira semana.
Trilha de leitura
Na ordem. Cada bloco depende do anterior.
Dias 1–2 — o negócio, sem código
Não pule esta parte por ser "não técnica". Metade dos bugs da squad é código correto em cima de um entendimento errado da operação.
- Como a operação funciona — o ciclo de ponta a ponta.
- Glossário — bip, furo, sobra, pack, FULL, retira, CD. Leia inteiro; esse é o vocabulário das reuniões.
- A venda entra → A compra → A conferência → Estoque e divergências → Faturamento e expedição.
- Por que existem dois sistemas — V1 (legado, Node) e V2 (Cerbero, Go) rodam ao mesmo tempo, no mesmo banco. Sem isso você não entende metade dos comportamentos.
Dias 3–5 — o modelo de dados
- O catálogo: SKU, marca, fornecedor — a base de tudo. SKU, base_sku, brand, cross_sku, ad, cd, supplier, sku_supplier, e as armadilhas de nome.
- Chaves de ligação —
sku_idesku_supplier_idcosturando venda, compra e conferência. - Banco de dados — o que é
cerbero(escrita) e o que épublic/supplier(leitura). - O ecossistema Karhub — os ~47 repositórios, o que cada um faz e como. Leia em modo mapa, não decorando: o objetivo é reconhecer o nome quando aparecer, e saber onde voltar. Junto, a dimensão — filas, tópicos e tabelas em números.
Semana 2 — a arquitetura
- Hexagonal — o formato de todo serviço.
- Eventos canônicos — o contrato central do ecossistema. Mudança aqui afeta todo mundo.
- Padrões obrigatórios — o checklist que seu PR precisa cumprir.
ml-webhook-adapter— o serviço de referência. Rode local, leia inteiro, é o template dos outros.- Fluxo conferência → faturamento → expedição.
Semana 3 — o porquê das decisões
- Os ADRs, em ordem. São curtos e cada um responde a um "por que diabos isso é assim". Os mais úteis para começar: ADR-001 (deadline de expedição), ADR-002 (conferência dinâmica), ADR-004 (cutover do faturamento V1→V2), ADR-011 (etiqueta unitária).
Setup do ambiente
O cerbero é um monorepo Go com go.work — todos os serviços num workspace só.
git clone <cerbero> && cd cerbero
go work sync # resolve os módulos do workspace
Cada serviço tem o mesmo Makefile. Comece pelo de referência:
cd ml-webhook-adapter
make docker/up # Postgres + emulador do Pub/Sub
make migrate # migrations do serviço
make test/unit # deve passar sem nada externo
make test/integration # sobe containers
make run
Outros targets que você vai usar: make lint, make mocks (regerar mocks depois de mexer em
port), make test/coverage, make docker/down.
Pré-requisito de banco: extensão pgcrypto (para gen_random_uuid()).
São 10 serviços mais o console web. O caminho normal é subir o serviço que você está mexendo e as dependências dele. Para entender o fluxo completo, leia os testes de integração em vez de tentar simular tudo.
Como a squad trabalha
Três pilares. Vendas & Marketplace, Compras & Supply Chain, NF-e/Conferência & Logística. Cada um tem uma pessoa de referência, mas ninguém é dono exclusivo — o mapa está no intro.
O contrato é sagrado. Qualquer mudança no modelo canônico de eventos ou em tópico Pub/Sub precisa de review dos três pilares. É a única coisa que quebra todo mundo de uma vez.
Todo serviço segue o mesmo formato. Serviço novo nasce do
service-boilerplate, não do zero.
Checklist do seu PR
Direto de Padrões obrigatórios:
- Idempotência — constraint de dedup no banco. Todo evento chega duas vezes um dia.
- PII — email e telefone com hash (SHA-256 + salt), documento mascarado, antes de publicar.
- Observabilidade — trace OpenTelemetry, métrica Prometheus em
/metrics, logslogestruturado comtrace_id. - Testes — unitário no domain/application, integração nos adapters.
- Schema do evento em
schemas/(Avro + JSON Schema), se você criou ou mudou evento. - README e Makefile atualizados.
Artefatos de repositório (título e descrição de PR, commit, comentário de código, doc) são escritos em inglês, mesmo que a conversa do dia a dia seja em português.
Os três erros clássicos de quem chega
1. Assumir que o CD é detalhe. Não é. Quase toda query da operação é filtrada por cd_id,
e uma proporção enorme dos "números errados" reportados é venda de um CD olhada com o filtro de
outro. Antes de investigar qualquer coisa, confira o CD.
2. Assumir que existe rastro peça-a-venda. Parece natural que o sistema saiba "compramos esta peça para aquela venda". Ele não sabe — e é de propósito. O bip casa oferta com demanda: chegaram 3 unidades do SKU X no CD 1, existem vendas abertas do SKU X no CD 1, as 3 vão para as mais urgentes. A explicação completa está em A conferência.
3. Confundir as unidades. O cliente compra 1, o SKU é vendido em par, o fornecedor entrega em caixa de 12. Existem três contagens diferentes e conversões entre elas em vários pontos. Quando um número parece errado, a primeira pergunta é em que unidade esse número está.
Onde pedir ajuda
Quando trouxer um problema da operação, traga junto — economiza horas de ida e volta:
- O número da venda (o do pack, quando houver).
- O CD.
- O SKU.
- A tela onde você viu e o que esperava ver.
- Se alguém desfez alguma coisa — desfazer apaga rastro e muda o diagnóstico.
E considere sempre a hipótese de ser o outro sistema: se a venda aparece pendente mas alguém já comprou, provavelmente foi comprada na V1.