csmkt docs
Staging Modo sandbox: nenhum dinheiro real Deploy automático pela branch main

Como o csmkt roda, como subir no seu computador e como o deploy acontece

Página de referência do ambiente de staging. Explica a infraestrutura no Dokploy, o caminho de um commit até o ar e o fluxo do produto. Não contém senhas, chaves nem dados de acesso.

O produto em uma tela

Marketplace peer-to-peer de skins de CS2, com preço em reais e pagamento por Pix. A plataforma não guarda itens: ela segura o dinheiro, verifica a entrega e só então paga o vendedor.

Sem bots de custódia

O vendedor envia a troca pela própria Steam. A plataforma confere nos inventários que o item certo saiu do vendedor e chegou ao comprador.

Dinheiro protegido

O valor fica reservado e só é liberado depois da janela de proteção da Steam (Trade Protection de 7 dias), menos a comissão do vendedor.

Pix com custódia de PSP

No desenho final, o dinheiro fica num PSP autorizado com subcontas e split. O ledger interno espelha a posição e é reconciliado todo dia.

Arquitetura

Seis repositórios separados por camada. O core é um monolito modular: a mesma imagem roda em três papéis (APP_ROLE).

Regra de integração: toda dependência externa fica atrás de uma porta com adapter real e adapter fake. No staging, todos os fakes estão ativos (ver Sandbox x real).
RepositórioO que tem
csmkt-platformCompose local, sandbox de Steam/PSP, OpenTofu (AWS), scripts, escopo, ADRs e runbooks
csmkt-contractsPacote @csmkt/contracts (Zod): dinheiro em centavos, erros, eventos, schemas da API
csmkt-apiCore de negócio
csmkt-aiBusca em linguagem natural, sugestão de preço, similares, suporte, moderação, resumo de disputa, risco
csmkt-webSite e área do usuário
csmkt-adminBackoffice dos operadores

Infra no Dokploy

Projeto csmkt no Dokploy. Um compose de infraestrutura e uma aplicação por processo, cada uma buildada a partir do próprio repositório.

Aplicações (buildadas dos repositórios)

ServiçoRepositório e buildFunçãoNome internoPúblico
webcsmkt-webSite e área do usuáriocsmkt-webcsmkt.odd-now.com
admincsmkt-adminBackofficecsmkt-admincsmkt-admin.odd-now.com
apicsmkt-api, stage runtimeHTTP e WebSocket (APP_ROLE=api)csmkt-apicsmkt-api.odd-now.com
workercsmkt-api, stage runtimeFilas BullMQ (APP_ROLE=worker)——
schedulercsmkt-api, stage runtimeJobs recorrentes e outbox (APP_ROLE=scheduler)——
api-migratecsmkt-api, stage migrateMigrations do Prisma; roda e termina——
aicsmkt-aiAPI da IA (AI_ROLE=api)csmkt-ai—
ai-workercsmkt-aiJobs Arq da IA (AI_ROLE=worker)——
ai-migratecsmkt-aiAlembic do schema ai; roda e termina——
sandboxcsmkt-platform, pasta sandboxSteam e PSP fakecsmkt-sandboxcsmkt-sandbox.odd-now.com
flagdcsmkt-platform, pasta compose/flagdFeature flags e kill switchescsmkt-flagd—

Compose infra (imagens públicas com versão fixa)

ServiçoImagemFunçãoPúblico
csmkt-postgrespgvector/pgvector:0.8.7-pg17-trixieBanco exclusivo do csmkt; roles de menor privilégio criadas no primeiro boot—
csmkt-pgbounceredoburu/pgbouncer:v1.26.1-p0Pool de conexões da API (modo transaction)—
csmkt-valkeyvalkey/valkey:8.1.11-alpine3.24Cache e filas (BullMQ)—
csmkt-s3rustfs/rustfs:1.0.4Arquivos de evidência (bucket privado, URL pré-assinada)csmkt-files.odd-now.com
csmkt-keycloakquay.io/keycloak/keycloak:26.8.1Login dos operadores do backoffice (OIDC)csmkt-auth.odd-now.com
csmkt-mailpitaxllent/mailpit:v1.32.0Recebe os e-mails do staging (nada sai para fora)—
csmkt-verdaccioverdaccio/verdaccio:7.0.2Registry npm interno do @csmkt/contracts, usado só no build—

Rede

  • Os serviços conversam pelos nomes internos (csmkt-*) numa rede do Docker. Nenhuma porta é publicada na internet.
  • Todo nome tem o prefixo csmkt- porque a rede é compartilhada com outros projetos do servidor.
  • Só web, admin, API, Keycloak, sandbox e S3 têm domínio. O TLS é terminado no servidor; o Traefik do Dokploy roteia pelo domínio.

Proteções do staging

  • Painel de controle do sandbox e console do Keycloak exigem senha extra.
  • Todas as páginas respondem com noindex.
  • Segredos ficam no ambiente dos serviços no Dokploy e no servidor, nunca nos repositórios.
  • Cada serviço tem limite de memória. O banco do staging tem só dados fictícios e pode ser recriado pelo seed.

Como o deploy funciona

Cada aplicação está ligada ao seu repositório, branch main, com deploy automático. Um push na main dispara o build no Dokploy.

  1. Push ou merge na main

    O GitHub App do Dokploy recebe o evento do repositório.

  2. Build de cada serviço ligado ao repositório

    Um push em csmkt-api rebuilda api-migrate, api, worker e scheduler; em csmkt-ai, os três da IA; em csmkt-platform, sandbox e flagd. O build usa o Dockerfile do próprio repositório, sem alteração.

  3. Dependência interna resolvida no build

    Api, web e admin instalam o @csmkt/contracts do registry interno. O hash do pacote precisa bater com o do pnpm-lock.yaml, então o registry guarda exatamente o tarball publicado pelo dono do projeto.

  4. Migrations

    api-migrate e ai-migrate rodam uma vez e terminam. Elas não bloqueiam a subida da API, por isso toda migration precisa ser compatível com a versão anterior (expand/contract), como o projeto já exige.

  5. Troca do container

    A versão nova sobe antes de a antiga sair (start-first), e a saúde é conferida pelo HEALTHCHECK de cada imagem. Se a atualização falhar, o serviço volta para a versão anterior.

Sem proteção de branch por enquanto: todo push na main vai direto para o staging. Rode make ci no repositório antes de mandar para a main.

O que não é automático

  • Compose infra: mudança em banco, Valkey, S3, Keycloak ou registry é feita por quem opera o servidor.
  • Versão nova do @csmkt/contracts: o tarball novo precisa ser publicado no registry interno antes do merge nos repositórios que usam a versão nova.
  • Flags do flagd: o arquivo de flags é configurado no serviço; mudar o flags.json no repositório não altera o staging sozinho.

Onde acompanhar

  • No Dokploy, projeto csmkt: cada serviço mostra os deploys, o log de build e o log do container.
  • Um deploy que falha no build não derruba a versão que está no ar.

Rodar tudo no seu computador

O ambiente local é o compose do csmkt-platform, com o mesmo sandbox do staging. Os repositórios são privados: o acesso é por convite.

Pré-requisitos

Docker Engine e Docker Compose v2
Node 24 com corepack (corepack enable) e uv para o Python 3.13
GNU Make, git e openssl. Os scanners do make ci rodam em containers.

1. Clonar os seis repositórios lado a lado

Os Makefiles usam caminhos relativos como ../csmkt-contracts, então as seis pastas ficam dentro de uma mesma pasta.

mkdir -p csmkt && cd csmkt
for r in platform contracts api ai web admin; do
  git clone git@github.com:Gacktto/csmkt-$r.git
done

2. Subir a stack (primeira vez)

cd csmkt-platform
git config core.hooksPath .githooks
cp .env.example .env
./scripts/gen-local-secrets.sh             # gera senhas e chaves locais no .env
make up-infra                              # banco, cache, S3, e-mail, Keycloak, flags, sandbox, registry
./scripts/registry-login.sh                # cria o publicador do registry local
make -C ../csmkt-contracts install publish # publica o @csmkt/contracts no registry local
make up                                    # builda e sobe api, worker, scheduler, ai, web e admin
make ps                                    # todos healthy
A ordem importa: as imagens de api, web e admin instalam o @csmkt/contracts do registry local durante o build. As migrations da API rodam sozinhas no make up. As da IA não: configure AI_DATABASE_MIGRATION_URL no .env do csmkt-ai e rode make -C ../csmkt-ai migrate.

3. Endereços locais

ServiçoEndereçoServiçoEndereço
Sitehttp://localhost:3000Backofficehttp://localhost:5173
APIhttp://localhost:4000IAhttp://localhost:8000
Sandbox (painel /control)http://localhost:4500Mailpithttp://localhost:8025
Keycloakhttp://localhost:8080Grafanahttp://localhost:3001

Todas as portas escutam só em 127.0.0.1 e podem ser trocadas no .env (variáveis HOST_PORT_*).

4. Dados de demonstração e testes

make seed-demo                       # vendedores com anúncios e compradores com saldo, pelos fluxos reais
make demo-order VARIANT=correct      # compra, troca, verificação, proteção e liberação
make demo-payout                     # saque: TOTP, KYC, chave Pix, cool-down
make ci                              # lint, testes, cobertura e scanners do repositório
make ci-all                          # ci de todos os repositórios + E2E (com a stack no ar)

Para ver a liberação na hora, o PROTECTION_HOLD_HOURS aceita fração no ambiente local (por exemplo 0.01). Em produção ele precisa ser de pelo menos 168 horas.

Como funciona por dentro

O fluxo de uma compra, do Pix até a liberação ao vendedor.

  1. Depósito

    O comprador gera uma cobrança Pix. O PSP avisa por webhook assinado; a API confere a assinatura sobre o corpo bruto, guarda o evento e reconsulta o PSP antes de creditar o saldo.

  2. Compra

    Numa única transação: o anúncio é travado no preço visto pelo comprador, as regras de risco rodam, a taxa é calculada e congelada na ordem e o valor passa de available para held.

  3. Troca na Steam

    O vendedor confirma e envia a oferta pela própria conta. A verificação compara os inventários: o item saiu do vendedor e um item com a mesma impressão digital chegou ao comprador. Caso ambíguo vai para disputa; nunca libera sozinho.

  4. Proteção

    A ordem fica em proteção durante a janela da Steam. Se a troca for revertida, o comprador é reembolsado e o vendedor é restringido.

  5. Liberação

    Fim da proteção sem reversão: o vendedor recebe o valor menos a comissão (regra semeada: 5% do vendedor) e o split é feito no PSP.

Estados da ordem

awaiting_seller_confirmation→ awaiting_trade_offer→ trade_offer_sent→ trade_accepted→ protection_hold→ completed

Saídas: cancelled (prazo vencido ou oferta inválida, com reembolso), trade_reversed (reversão durante a proteção) e disputed, que termina em completed ou refunded por decisão de operador. Os prazos rodam em jobs atrasados mais uma varredura a cada 5 minutos.

Ledger de partidas dobradas

Contas

  • Do usuário: available, held, payout_pending, med_hold.
  • Da plataforma: psp_clearing (espelho do PSP), revenue_commission, revenue_fees, psp_costs, losses, promo_expense.

Garantias

  • A soma de cada lançamento é zero, garantida pelo próprio banco.
  • Saldo de usuário nunca fica negativo; lançamento nunca é alterado (correção é estorno).
  • Integridade conferida de hora em hora; divergência congela saques. Reconciliação diária com o extrato do PSP.

Saque

KYC pela subconta do PSP (um CPF por conta), chave Pix só do mesmo CPF, 2FA com reconfirmação, espera de 48 horas depois de mudanças sensíveis, limites diários por nível e revisão manual do primeiro saque.

IA

A IA é um processo separado e só adiciona: se cair ou demorar, compra e venda seguem normalmente. Ela nunca libera dinheiro nem decide disputa; o score de risco só pode mandar algo para revisão.

Sandbox x real

O staging roda inteiro contra simulações. "Fase concluída" no roadmap significa implementada e testada contra o sandbox.

IntegraçãoNo stagingPara ir a produção
PSP PixPSP fake do sandbox (cobrança, webhook, saque, extrato)Escolher o PSP e escrever o adapter real. A API recusa subir em produção com o PSP do sandbox.
SteamLogin e inventários fake, trocas simuladasValidar a verificação de troca em contas reais (roteiro do ADR-0009)
IAProvider fake (determinístico)Provider real configurado
Chaves de criptografiaChave mestra localKMS gerenciado
E-mailMailpit (nada sai do servidor)Serviço de e-mail transacional
Antes de qualquer dinheiro real faltam, além do técnico: validação jurídica do modelo de custódia, contrato com o PSP, PLD/FT, LGPD, tributação e pentest externo.