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
Dinheiro protegido
Pix com custódia de PSP
Arquitetura
Seis repositórios separados por camada. O core é um monolito modular: a mesma imagem roda em três papéis (APP_ROLE).
| Repositório | O que tem |
|---|---|
csmkt-platform | Compose local, sandbox de Steam/PSP, OpenTofu (AWS), scripts, escopo, ADRs e runbooks |
csmkt-contracts | Pacote @csmkt/contracts (Zod): dinheiro em centavos, erros, eventos, schemas da API |
csmkt-api | Core de negócio |
csmkt-ai | Busca em linguagem natural, sugestão de preço, similares, suporte, moderação, resumo de disputa, risco |
csmkt-web | Site e área do usuário |
csmkt-admin | Backoffice 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ço | Repositório e build | Função | Nome interno | Público |
|---|---|---|---|---|
web | csmkt-web | Site e área do usuário | csmkt-web | csmkt.odd-now.com |
admin | csmkt-admin | Backoffice | csmkt-admin | csmkt-admin.odd-now.com |
api | csmkt-api, stage runtime | HTTP e WebSocket (APP_ROLE=api) | csmkt-api | csmkt-api.odd-now.com |
worker | csmkt-api, stage runtime | Filas BullMQ (APP_ROLE=worker) | — | — |
scheduler | csmkt-api, stage runtime | Jobs recorrentes e outbox (APP_ROLE=scheduler) | — | — |
api-migrate | csmkt-api, stage migrate | Migrations do Prisma; roda e termina | — | — |
ai | csmkt-ai | API da IA (AI_ROLE=api) | csmkt-ai | — |
ai-worker | csmkt-ai | Jobs Arq da IA (AI_ROLE=worker) | — | — |
ai-migrate | csmkt-ai | Alembic do schema ai; roda e termina | — | — |
sandbox | csmkt-platform, pasta sandbox | Steam e PSP fake | csmkt-sandbox | csmkt-sandbox.odd-now.com |
flagd | csmkt-platform, pasta compose/flagd | Feature flags e kill switches | csmkt-flagd | — |
Compose infra (imagens públicas com versão fixa)
| Serviço | Imagem | Função | Público |
|---|---|---|---|
csmkt-postgres | pgvector/pgvector:0.8.7-pg17-trixie | Banco exclusivo do csmkt; roles de menor privilégio criadas no primeiro boot | — |
csmkt-pgbouncer | edoburu/pgbouncer:v1.26.1-p0 | Pool de conexões da API (modo transaction) | — |
csmkt-valkey | valkey/valkey:8.1.11-alpine3.24 | Cache e filas (BullMQ) | — |
csmkt-s3 | rustfs/rustfs:1.0.4 | Arquivos de evidência (bucket privado, URL pré-assinada) | csmkt-files.odd-now.com |
csmkt-keycloak | quay.io/keycloak/keycloak:26.8.1 | Login dos operadores do backoffice (OIDC) | csmkt-auth.odd-now.com |
csmkt-mailpit | axllent/mailpit:v1.32.0 | Recebe os e-mails do staging (nada sai para fora) | — |
csmkt-verdaccio | verdaccio/verdaccio:7.0.2 | Registry 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.
- Push ou merge na
mainO GitHub App do Dokploy recebe o evento do repositório.
- Build de cada serviço ligado ao repositório
Um push em
csmkt-apirebuildaapi-migrate,api,workerescheduler; emcsmkt-ai, os três da IA; emcsmkt-platform, sandbox e flagd. O build usa oDockerfiledo próprio repositório, sem alteração. - Dependência interna resolvida no build
Api, web e admin instalam o
@csmkt/contractsdo registry interno. O hash do pacote precisa bater com o dopnpm-lock.yaml, então o registry guarda exatamente o tarball publicado pelo dono do projeto. - Migrations
api-migrateeai-migraterodam 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. - Troca do container
A versão nova sobe antes de a antiga sair (
start-first), e a saúde é conferida peloHEALTHCHECKde cada imagem. Se a atualização falhar, o serviço volta para a versão anterior.
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.jsonno 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
corepack enable) e uv para o Python 3.13make 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
@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ço | Endereço | Serviço | Endereço |
|---|---|---|---|
| Site | http://localhost:3000 | Backoffice | http://localhost:5173 |
| API | http://localhost:4000 | IA | http://localhost:8000 |
Sandbox (painel /control) | http://localhost:4500 | Mailpit | http://localhost:8025 |
| Keycloak | http://localhost:8080 | Grafana | http://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.
- 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.
- 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
availableparaheld. - 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.
- 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.
- 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
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ção | No staging | Para ir a produção |
|---|---|---|
| PSP Pix | PSP 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. |
| Steam | Login e inventários fake, trocas simuladas | Validar a verificação de troca em contas reais (roteiro do ADR-0009) |
| IA | Provider fake (determinístico) | Provider real configurado |
| Chaves de criptografia | Chave mestra local | KMS gerenciado |
| Mailpit (nada sai do servidor) | Serviço de e-mail transacional |