Platform Requirements: SAR — Força de Vendas
Status: ✅ Block D COMPLETO (Steps 27-32) — fast-track via STACK.md v2.2
Cliente: JCS Sistemas
Última atualização: 2026-05-27
Este documento é um espelho consolidado de decisões já feitas em STACK.md v2.2, CODING-RULES.md v2.0, ADRs 0001-0006, e Step 10a (Platform Strategy). Não duplica conteúdo — referencia. STACK.md continua sendo source of truth para qualquer decisão técnica.
Stakeholder técnico
| Item |
Valor |
| Tech Lead |
Julian (acumulado com PO + Champion — solo founder mode até 1º cliente) |
| Nível técnico do PO |
Muito técnico (autor de STACK.md + CODING-RULES.md) |
| Time de desenvolvimento MVP |
Apenas Julian até 1º cliente; +1-2 devs depois |
| Cultura técnica JCS |
Tech maturity alta — 11-50 pessoas, anos de software profissional |
Decisões já feitas (referência cruzada)
| Decisão |
Onde está consolidada |
| Stack canônica completa |
STACK.md v2.2 (FONTE DA VERDADE) |
| Invariantes de código e pegadinhas críticas |
CODING-RULES.md v2.0 |
| Multi-tenancy BD-por-workspace |
ADR 0006 (substituiu row-level tenantId) |
| master-login como IdP |
ADR 0005 (substituiu Keycloak) |
| Migração AWS sa-east-1 → Proxmox on-prem BR |
ADR 0004 |
| SLO defaults por endpoint/job/fluxo |
ADR 0001 |
| Tags Nx canônicas (scope / type / domain) |
ADR 0002 |
| PWA mobile-first iOS para Rafael |
Step 10a |
| Desktop-first para Sandra/Daniel/Alice |
Step 10a + brand.md |
| iPad first-class para Daniel |
Step 10a |
| Offline read+write com sync (Rafael) |
Step 10a |
| Coexistência com app Android legado |
Step 10a |
| Sem app store no MVP |
Step 10a + STACK.md §18 |
| pt-BR only no MVP, i18n-ready |
Step 16 |
| LGPD by design |
STACK.md §22 + CODING-RULES.md |
| brand.md |
identidade visual canônica |
03-visual-direction.md |
direção visual completa |
Tech Stack (Step 28 — espelho consolidado de STACK.md v2.2)
Camadas principais
| Camada |
Decisão canônica |
| Runtime |
Node 24 LTS · pnpm 11.1 · TypeScript 5.9 |
| Monorepo |
Nx 22.7 (apps/api + apps/api-worker + apps/web + apps/web-e2e + libs/) com 3 tags canônicas (scope / type / domain) — ADR 0002 |
| Backend |
NestJS 11.1 (Express 5) · Prisma 7 · PostgreSQL 18 · nestjs-cls · @nestjs/terminus · @nestjs/throttler + Valkey storage |
| Frontend |
React 19.2 + Compiler · Vite 8 (Rolldown) · Ant Design 6.4 · TanStack Query 5.100 · TanStack Router · Zustand 5 |
| API |
REST + OpenAPI 3.1 + RFC 9457 Problem Details · Zod 4 (pnpm catalog) + nestjs-zod + react-hook-form (zodResolver) |
| Auth |
Guards NestJS + jose + master-login (IdP OAuth2/OIDC próprio em VM Proxmox; HS256→RS256 roadmap) · argon2id no IdP — ADR 0005 |
| Multi-tenancy |
BD-por-workspace — cluster Postgres dedicado por cliente, resolvido via get_workspace_connection no master-login. Sem coluna tenantId em modelos — isolamento físico — ADR 0006 |
| Secrets |
HashiCorp Vault (KV v2) self-host · Vault Agent injeta env vars no entrypoint do container |
| Observabilidade |
Pino + nestjs-pino 10.3 · OpenTelemetry (Traces/Metrics GA, Logs Beta) · Grafana Cloud LGTM · Sentry |
| Feature flags |
OpenFeature SDK + GrowthBook self-host |
| Filas |
BullMQ 5.77 + @nestjs/bullmq 11 · Bull Board · Valkey em VM/LXC Proxmox |
| Cache |
@nestjs/cache-manager v3 + cache-manager 6 + @keyv/redis + cacheable (L1) |
| Real-time |
Socket.IO 4 + @socket.io/redis-adapter (Valkey) · SSE via @Sse() nativo NestJS |
| Uploads |
MinIO (S3-compat) presigned POST policy · AWS SDK v3 · Uppy + @uppy/aws-s3 · ClamAV worker BullMQ · sharp 0.34 |
| Email |
Resend (SaaS — únicas exceções SaaS são email e CDN por questão de deliverability/borda) + React Email via BullMQ |
| Testes |
Vitest 4.1 · Testcontainers 12 · Supertest 7.2.2 (encapsulado) · Playwright 1.60 |
| Qualidade |
ESLint 10.4 flat · typescript-eslint 8.59 · Prettier 3.8.3 · eslint-plugin-importx 4.16.2 · Husky 9 + lint-staged 17 · gitleaks |
| CI/Deploy |
GitHub Actions + Nx Cloud · Trivy gate · pin actions por SHA · Docker multi-stage node:24-alpine · Ansible/SSH para VMs Proxmox com docker-compose rolling (backend) · Cloudflare + Nginx servindo SPA estática (frontend) |
| Infraestrutura |
Proxmox on-prem BR — substitui AWS sa-east-1 — ADR 0004. Self-host Postgres, Valkey, MinIO, master-login, Vault, GrowthBook, PostHog (novo) |
Decisões frontend específicas do SAR (decorrentes de Block C)
- PWA mobile-first iOS para Rafael — Service Worker + Web Push + manifest + offline read+write
- Desktop SPA para Sandra/Daniel/Alice (mesmo bundle React, layouts diferentes)
- iPad first-class para Daniel (testes regulares em iPad Safari)
- Code-splitting por cockpit (TanStack Router lazy routes)
- Service Worker crítico para Rafael offline (IndexedDB queue + sync)
- Plus Jakarta Sans self-host (não Google Fonts CDN — LGPD + performance)
- Dark mode elegante (especialmente Rafael à noite)
- Build target: ES2023 (
noUncheckedIndexedAccess ON, NodeNext module resolution)
Rationale (curto)
A stack JCS v2.2 foi calibrada para:
- LGPD by design (datacenter BR, isolamento físico multi-tenant, redact em logs)
- Velocidade de desenvolvimento (Node/Nest/Prisma stack TypeScript end-to-end)
- Custo operacional baixo (self-host Proxmox para tudo que não é deliverability/edge)
- Velocidade de iteração (Nx affected, code-splitting, hot reload Vite Rolldown)
- Solo founder mode (toolchain conhecido pelo PO, sem learning curve)
Para alterar qualquer decisão fora desta tabela: RFC em docs/adr/NNN-titulo.md.
Integrations (Step 29)
Decisões fechadas
| Integração |
Provider escolhido |
Por quê |
Notas |
| Pagamento |
Iugu |
BR-focused, assinaturas recorrentes nativas, boleto/PIX/cartão suportados, ticket B2B BR padrão |
Webhook handler via NestJS controller + BullMQ para retries. Receita reconhecida no momento do paid event. |
| WhatsApp Business |
Oficial Meta (WhatsApp Cloud API) |
Sem intermediário, templates aprovados direto pela Meta, mais seguro a longo prazo |
Setup mais burocrático (verificação Business + templates approval). Custo por mensagem. Templates centralizados em libs/shared/whatsapp-templates. |
| Analytics de produto |
PostHog self-host (Proxmox) |
Self-host alinha STACK.md (BR + LGPD). Cobre product analytics, session replay, feature flags. |
Roda em VM/LXC Proxmox separada. Eventos via SDK no frontend. Dashboards customizados por cockpit. |
| Email transacional |
Resend (já em STACK.md §15) |
Já decidido |
React Email para templates · BullMQ jobs · DPA assinado |
| Identidade (IdP) |
master-login (próprio, JCS) — ADR 0005 |
Já decidido |
OAuth2/OIDC, argon2id |
| Secrets |
HashiCorp Vault self-host |
Já decidido |
KV v2, Vault Agent no container |
| Object storage |
MinIO self-host |
Já decidido |
S3-compat, presigned POST policy, ClamAV worker |
| CDN edge |
Cloudflare |
Já decidido em STACK.md §18 |
DNS, edge cache, DDoS, certificados |
| Logging |
Grafana Cloud LGTM + Sentry |
Já decidido |
OTel + Pino + Sentry |
| Geolocation (GPS check-in) |
Browser navigator.geolocation nativo |
Sem provider externo |
Web API padrão |
⚠️ Decisão aberta: IA generativa
Julian quer estudar todas as opções antes de cravar. Recomendação canônica: abstração multi-provider desde dia 1.
Arquitetura proposta:
- Camada de abstração: Vercel AI SDK (
ai package) ou LiteLLM proxy (Node SDK)
- Cliente NestJS chama interface única; troca de provider é configuração
- Providers candidatos a A/B (com critérios de avaliação):
| Provider |
Pros |
Cons |
Score qualitativo |
| Anthropic (Claude) |
Excelente em raciocínio analítico + pt-BR · JSON estruturado nativo · explicabilidade forte (alinha SAR) |
Custo médio · ecossistema menor que OpenAI |
⭐⭐⭐⭐⭐ alinhamento com diferencial |
| OpenAI (GPT) |
Ecossistema maior · mais SDKs/tools · function calling maduro |
Drift de qualidade entre versões · custo competitivo |
⭐⭐⭐⭐ |
| Local/Ollama |
Sem custo recorrente · máximo controle/privacidade |
Qualidade inferior · custo de infra Proxmox · velocidade variável |
⭐⭐ para MVP, ⭐⭐⭐⭐ se LGPD for ultra-rigoroso |
| Multi-provider (LiteLLM) |
Hedge total · pode usar local para tarefas simples + cloud para complexas |
Complexidade de manutenção |
⭐⭐⭐⭐⭐ estratégico |
Princípio: estrutura o código para ser provider-agnostic. PR de IA não tem import OpenAI from 'openai' — usa interface JCS.
Marco de decisão: quando 1º cliente fechar e Julian tiver tempo de benchmark dedicado. Até lá, padrão temporário = Anthropic Claude Sonnet/Opus via SDK direto, mas isolado atrás de interface.
Categorias de integração futura (mapa, sem decisão MVP)
| Categoria |
Quando decidir |
Candidatos |
| CRM próprio JCS (vender SAR com SAR — dogfood) |
Y1 |
O próprio SAR adaptado |
| Assinatura digital de contratos |
Y1 |
DocuSign · ClickSign (BR) · D4Sign (BR) |
| NFe / NFSe (cobrança JCS para clientes) |
Y1 quando volume justifica |
NFe.io · Bling · Iugu pode embutir |
| CDP / nurturing de leads |
Y1+ |
PostHog cobre boa parte; eventualmente HubSpot/RD Station |
| Helpdesk / suporte ao cliente |
Pós-MVP |
Crisp · Zendesk · self-host Cal.com + email |
| Status page pública |
Pós-MVP |
Statuspage.io · Instatus · self-host Cachet |
Account ownership (quem cria/gerencia)
| Integração |
Conta de quem |
Notas |
| Iugu, Resend, Anthropic/OpenAI, Cloudflare, Meta WhatsApp |
JCS Sistemas |
Único proprietário; cobrança vai pra JCS |
| MinIO, master-login, Vault, GrowthBook, PostHog |
JCS Sistemas self-host |
Roda em VMs Proxmox JCS |
| Google Business Profile (JCS) |
JCS Sistemas |
Reivindicar e manter |
Contact Strategy (Step 30)
Primary contact method
Form de demo (/contato no site marketing) — alinha com sales-led motion (Step 5).
| Campo |
Obrigatório |
Por quê |
| Nome |
Sim |
Personalização do follow-up |
| Email corporativo |
Sim |
Canal principal · validador de "B2B real" |
| Telefone (com DDD) |
Sim |
Permite ligação direta · WhatsApp follow-up |
| Empresa |
Sim |
Qualificação inicial |
| Cargo / função |
Sim |
Identifica se é dono/diretor (decisor) ou supervisor (influenciador) |
| Quantos representantes externos |
Sim |
Qualificação principal (sweet spot 5-50) |
| ERP atual |
Sim |
Identifica origem do lead (Grupo 2 da concorrência) |
| Cidade/UF |
Sim |
Roteamento regional eventual |
| Como nos conheceu |
Opcional |
Atribuição de canal (indicação? Google? feira? parceiro?) |
| Mensagem |
Opcional |
Captura intent custom |
Channels (canais de contato disponíveis)
| Canal |
Quando aparece |
Quem responde |
| Form de demo (CTA principal) |
Em toda página + header sticky |
SDR JCS (Julian no início) |
Email (contato@sarjcs.com.br ou similar) |
Footer |
SDR |
| Telefone JCS |
Footer + página /contato |
SDR (horário comercial BR) |
| WhatsApp JCS Business |
Footer + página /contato (clica e abre app) |
SDR |
Página /parceiros |
Captura indicações de canal |
Account manager (Julian no início) |
| Chat ao vivo |
❌ NÃO no MVP |
Volta como decisão pós-MVP |
Form requirements técnicos
- Anti-spam: hCaptcha ou Cloudflare Turnstile (não Google reCAPTCHA — LGPD)
- Validação client-side: Zod schema compartilhado com o backend
- Submit → cria lead no CRM JCS · dispara notificação Slack/email para SDR · responde "Recebemos seu contato — Julian responde em até 4h úteis"
- Rate limit: 5 submissions/email/h · 10/IP/h via
@nestjs/throttler
- LGPD: checkbox de consentimento explícito + link para política de privacidade
- Idempotency:
Idempotency-Key header (Zod + nestjs-zod já cobrem)
AI opportunity em contato
Pós-MVP: chatbot pré-qualificador do lead na própria página de contato. Usa o stack de IA generativa (a definir) para responder dúvidas básicas e qualificar antes do SDR atender. Não no MVP — solo founder não vai operar isso bem.
UX implications
- Form aparece em modal/drawer ao clicar "Agende demo" (não navegação a
/contato)
- Após submit, mensagem clara + próximos passos ("Julian envia uma proposta em até 24h úteis")
- Email automático imediato confirmando recebimento (Resend + React Email)
- Lead score automático no CRM (tamanho da equipe + cargo)
Multilingual & SEO (Step 31)
Multilingual (já decidido em Step 16)
- pt-BR only no MVP · arquitetura i18n-ready (todas strings em
pt-BR.json)
- en preparado no código, sem tradução
- es (LatAm) fora de escopo (requer adaptação fiscal por país)
URL structure técnica
- Domínio:
sarjcs.com.br (proposta — verificar disponibilidade)
- pt-BR (default):
<dominio>/<slug>
- en futuro:
<dominio>/en/<slug>
- App produto:
app.sarjcs.com.br/ ou <dominio>/app/ (decidir em PRD)
- Slug: lowercase, hífen, ASCII, sem stopwords desnecessárias
Translation workflow (futuro)
- Strings vivem em
libs/shared/i18n/locales/pt-BR.json (single source)
- Tradução
en.json quando ativar: copy mantido fiel ao tom "consultor sênior" + variantes culturais aplicáveis
- Sincronização via diff de chaves: CI quebra build se chave faltar em algum locale ativo
Technical SEO requirements (espelha Step 17)
| Item |
Implementação |
| Meta tags dinâmicas |
Vite + React Helmet por rota |
| Sitemap.xml |
Gerado por script no build · submit Google Search Console |
| robots.txt |
Permitir crawling em marketing; noindex em /app/ (produto privado) |
| Structured data (JSON-LD) |
Organization (JCS) · SoftwareApplication (SAR home) · Product+Offer (preços) · Article (blog/cases) · FAQPage · BreadcrumbList |
| Open Graph + Twitter Cards |
Por rota, com imagem dedicada (screenshot do produto) |
| hreflang tags |
Não no MVP (single language); preparado quando i18n ativar |
| Canonical URLs |
Em toda página, mesmo o domínio principal |
| 404 customizada |
Line art mono JCS Blue + "Voltar pra home" |
| Core Web Vitals |
Lighthouse > 90 · LCP < 2.5s · CLS < 0.1 · INP < 200ms |
| Schema.org test |
Validação no Google Rich Results Test antes de cada deploy |
Performance budgets (espelha Step 24)
| Métrica |
Target |
Bloqueio |
| Lighthouse Performance (mobile) |
≥ 90 |
CI quebra se < 85 |
| FCP |
< 1.5s |
— |
| LCP |
< 2.5s |
CI alerta se > 3s |
| CLS |
< 0.1 |
— |
| INP |
< 200ms |
— |
| Bundle inicial por entry |
< 200KB gzipped |
CI alerta se > 250KB |
| TTI Rafael 3G (PWA) |
< 3s |
Validação manual em dispositivo |
Maintenance Ownership
MVP (solo founder mode)
| Categoria |
Owner |
Frequência |
| Stack updates (npm deps, ADRs, RFC) |
Julian |
Trimestral (alinhar com STACK.md cadence) |
| Deploys (backend + frontend) |
Julian via Ansible/SSH |
A cada PR mergeado |
| Infraestrutura Proxmox (VMs, snapshots, backup) |
Julian |
Manutenção mensal, backup diário automatizado |
| Vault rotation, master-login chaves |
Julian |
Trimestral / on-incident |
| Monitoramento Grafana + Sentry |
Julian |
On-call 24/7 (PME pequena) |
| Integrações (Iugu, Resend, Meta WhatsApp, Cloudflare) |
Julian |
On-issue |
| LGPD ANPD / DPO |
Julian (com possível advogado externo) |
On-request |
| Atualização de templates WhatsApp Meta |
Julian + revisor de tom |
On-mudança |
Pós-MVP (Y1+)
| Categoria |
Owner futuro |
| Infraestrutura |
DevOps/SRE dedicado |
| Backend dev |
Time JCS (1-2 devs) |
| Frontend dev |
Time JCS (1-2 devs) |
| QA |
QA dedicado ou compartilhado com dev |
| LGPD / Compliance |
DPO formal (Julian acumula, depois separa) |
Risk register
| Risco |
Probabilidade |
Impacto |
Mitigação |
| Meta muda regras WhatsApp Business |
Média |
Alto |
Arquitetura plug-in · alternativa Telegram/SMS no roadmap (Step 9, 10) |
| Anthropic/OpenAI muda pricing ou política |
Média |
Alto |
Abstração multi-provider (LiteLLM/AI SDK) · capacidade de trocar provider · sempre considerar local fallback |
| Iugu instabilidade |
Baixa |
Alto |
Multi-provider de pagamento (preparar arquitetura para alternar Pagar.me como backup) |
| Cloudflare CDN issue |
Baixa |
Médio |
Migrar para AWS CloudFront / Bunny CDN possível em <1 dia |
| Proxmox failure |
Baixa |
Crítico |
Backup snapshot diário · Plano B: re-provisionamento em outra infra (custo de RTO ~4-8h) |
| Solo founder ausência prolongada |
Média |
Crítico |
Documentação extensiva em CODING-RULES.md · todos os secrets em Vault recuperável · contratar 1 dev assim que possível |
Final synthesis
Visão executiva
O SAR roda na stack canônica JCS v2.2 sem desvios. Decisões de plataforma específicas do produto vivem em Step 10a (Platform Strategy) e neste documento. STACK.md é a fonte da verdade para qualquer questão técnica não específica do SAR.
Tabela síntese (entrar no Brief executivo)
Próximos passos
- Phase 3 (PRD): detalhar requirements por feature consumindo este doc
- Phase 4 (UX Specs): cada cockpit referencia constraints de plataforma
- Phase 5 (Agentic Dev): scaffolding Nx + setup CI/CD via STACK.md
Block D COMPLETO. Próximo: Block E — Wrap-up (Steps 33-36).