Pular para o conteúdo principal

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 frase que explica o resto

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ênciaPor quê
O prazo manda em tudoEntre 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 produtoPreço, disponibilidade e prazo mudam por fornecedor. Escolher de quem comprar é uma decisão de sistema, não de cadastro.
Tudo é por CDA 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:

EtapaServiçoEscreve em
Venda entra (Mercado Livre)ml-webhook-adaptercerbero.webhook_notifications → Pub/Sub
Venda entra (Shopify/Yampi)shopify-webhook-adapteridem
Pedido persistidoorder-processorcerbero.order, order_item, expedition
O que comprar e de quempurchase-recommendationcerbero.purchase_recommendation
Fechar e mandar ao fornecedorpurchase-closingcerbero.purchase_order*
NF-e de entrada e conferênciasupplier-invoice-receivingcerbero.supplier_invoice*, conference_scan
Estoque e alocaçãowms-servicealocação, espelho Omie
Telas da operaçãocompras-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.

O Cerbero é uma fatia de algo bem maior

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.

  1. Como a operação funciona — o ciclo de ponta a ponta.
  2. Glossário — bip, furo, sobra, pack, FULL, retira, CD. Leia inteiro; esse é o vocabulário das reuniões.
  3. A venda entraA compraA conferênciaEstoque e divergênciasFaturamento e expedição.
  4. 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

  1. 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.
  2. Chaves de ligaçãosku_id e sku_supplier_id costurando venda, compra e conferência.
  3. Banco de dados — o que é cerbero (escrita) e o que é public/supplier (leitura).
  4. 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

  1. Hexagonal — o formato de todo serviço.
  2. Eventos canônicos — o contrato central do ecossistema. Mudança aqui afeta todo mundo.
  3. Padrões obrigatórios — o checklist que seu PR precisa cumprir.
  4. ml-webhook-adapter — o serviço de referência. Rode local, leia inteiro, é o template dos outros.
  5. Fluxo conferência → faturamento → expedição.

Semana 3 — o porquê das decisões

  1. 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()).

Você não roda o ecossistema inteiro na sua máquina

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, log slog estruturado com trace_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:

  1. O número da venda (o do pack, quando houver).
  2. O CD.
  3. O SKU.
  4. A tela onde você viu e o que esperava ver.
  5. 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.