Peça sob encomenda virava bagunça financeira
Compra com dinheiro próprio, aplica markup, cliente às vezes atrasa — e o rastro se perde quando vários carros acumulam ao mesmo tempo.
Oficina, loja de peças e acompanhamento de serviço no mesmo sistema. A loja não pede login;
o /admin exige sessão de um único usuário — o dono.
Pedro é mecânico autônomo especializado em motor VW TSI/MSI, em São Luís. Trabalha sozinho, com demanda volátil de 1 a 6 carros por dia — e tudo passava pelo WhatsApp.
Compra com dinheiro próprio, aplica markup, cliente às vezes atrasa — e o rastro se perde quando vários carros acumulam ao mesmo tempo.
Óleo, filtros, pneus, rodas — sem visibilidade de margem, sem alerta de mínimo.
Cada carro, cada peça, cada combinado — tudo vivendo na memória e no histórico de conversas do WhatsApp.
Um sistema que cobre a operação inteira — e uma loja pública de peças, servidos pelo mesmo binário Rust.
A loja não pede login: qualquer cliente navega o catálogo, monta carrinho e fecha pedido direto. O
/admin já é outra história — exige sessão, e a autenticação é
single-admin: o sistema tem um usuário só, o dono.
Loja pública com catálogo, carrinho, checkout com PIX e acompanhamento do pedido; site institucional da oficina; e um painel admin com 8 módulos.
O FAQ do site é a cara da marca — não é copy de estúdio, é a voz do próprio Pedro, publicada no ar:
— Mexe com Fiat?
“Deus me livre.”— Meu carro tem um defeito que ninguém acha. Tem jeito?
“Tem. Eu sou o ‘ninguém’ que as outras oficinas mandam você procurar.”
O binário aplica as migrations no boot, expõe a API sob /api, aplica
rate-limit, gera sitemap.xml/robots.txt —
e ainda serve o build do SPA. Sem Node em produção, mesma origem, sem CORS. O mesmo executável também
roda como CLI, para tarefas administrativas de bastidor.
Na frente, Caddy cuida do TLS automático. Atrás, PostgreSQL 17 sem porta exposta.
Cada uma existe no código e é exercitada por teste.
Toda rota responde { ok, data } ou { ok, error
} — até falhas do framework: rejeições de extractor e fallbacks 404/405 são remapeados para o
mesmo envelope. Erro interno nunca vaza detalhe. Confirmado no ar: /api/auth/me devolve 401 com {"error":"credenciais
inválidas ou sessão expirada","ok":false}.
O pedido é rastreado por um token HMAC-SHA256 do UUID, com verificação constant-time — sem linha no banco, sem expiração. Token errado, ausente ou pedido inexistente devolvem o mesmo 404 uniforme. A API nunca revela se um pedido existe.
O checkout aceita apenas { produto_id, quantidade }; #[serde(deny_unknown_fields)] rejeita com 422 qualquer preço forjado, e o
total é recalculado do banco. Dinheiro nunca em float: numeric(12,2) →
Decimal → string no JSON.
O BR Code (EMV/BACEN, TLV) é montado em Rust, com o CRC-16/CCITT-FALSE implementado à mão e validado
contra o vetor canônico "123456789" → "29B1". O front só renderiza o copia-e-cola.
O recálculo do custo médio ponderado roda dentro de SELECT … FOR UPDATE;
um teste de concorrência prova que duas saídas simultâneas não deixam o saldo negativo.
Totais, baixa de estoque e custo médio vivem em Rust — testável e versionado; o SQL guarda só o gatilho
de atualizado_em e colunas geradas. Handlers finos recebem o extractor
Admin como argumento, então autenticação vira requisito de tipo — e um
teste tabelado de guard 401 cobre a maior parte das rotas. SQLx checa as queries em tempo de compilação
contra o schema real.
A versão anterior não era protótipo. Era um sistema real, construído em 8 sprints, com autenticação, ordens de serviço e financeiro marcados como "validada em produção" — o Pedro usava. Estoque, agenda e loja já estavam implementados. Reescrever um sistema que funciona é uma decisão de peso.
Sair da dependência de plataformas de terceiros; o dado e a infraestrutura passam a morar em VPS própria.
A VPS já existia e já rodava outra coisa. Consolidar em vez de somar mais um plano.
Regra de negócio no código, testada e versionada, em vez de espalhada pelo banco — tipos e testes fechando a porta para a classe de erro que aparece quando a lógica vive em SQL e em RLS.
Rust é a aposta declarada do estúdio. Esta página é a /stack aplicada na prática.
X-Frame-Options: DENY
· nosniff · Referrer-Policy) + HSTS só em produção. Confirmado no ar.Nota honesta: eventos sensíveis são gravados como log estruturado, não em uma tabela de auditoria durável.
Contados contra o código-fonte, em julho de 2026.
Os 236 do Rust se dividem em 175 de integração #[sqlx::test] contra
Postgres real, 53 #[test] e 8 #[tokio::test].
Os 209 do Vitest cobrem schemas Zod, formatadores e a camada de API. Os 8 de Playwright rodam a loja e o
admin em desktop e mobile (390×844, sem overflow horizontal).
Build Docker de 3 estágios: um estágio compila o SPA, outro compila o binário Rust em release (sem banco no build), e a imagem final leva só o binário, as migrations e o build do SPA — rodando como usuário não-root.
No compose de produção, o banco e a aplicação ficam sem porta exposta no host; só o Caddy responde nas
portas 80 e 443. Backups cifrados, off-site, com retenção de 30 dias. Deploy é git pull + subir os containers de novo; as migrations aplicam no boot.
Nada aqui é estimativa: cada número foi contado no código-fonte em julho de 2026.
Além dos seis acima: 17 enums, 3 views e 6 migrations no schema; cerca de 9,7 mil linhas de Rust de produção e 20,8 mil de TypeScript/TSX; a ordem de serviço é uma máquina de 6 estados; 149 commits no histórico.
Do primeiro commit ao deploy — a gente cuida da stack inteira.