# 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): `/` - en futuro: `/en/` - App produto: `app.sarjcs.com.br/` ou `/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) ``` ───────────────────────────────────────────────────────── SAR — Platform Requirements Summary ───────────────────────────────────────────────────────── Stack: Node 24 · NestJS 11 · Prisma 7 · PG 18 · React 19 + Vite 8 + AntD 6.4 · Zod 4 · BullMQ 5.77 · Socket.IO 4 · TanStack Query/Router · Zustand Multi-tenant: BD-por-workspace (cluster PG dedicado/cliente) — ADR 0006 Auth: master-login (IdP próprio) — ADR 0005 Infra: Proxmox on-prem BR — ADR 0004 Distribução: PWA mobile-first iOS · Desktop-first · iPad first-class Integrations: Pagamento: Iugu (boleto/PIX/cartão + assinaturas recorrentes) WhatsApp: Oficial Meta (Cloud API) IA: Decisão ABERTA — abstração multi-provider (LiteLLM/AI SDK) · default temporário: Anthropic Claude Analytics: PostHog self-host (Proxmox) Email: Resend (transacional) Storage: MinIO self-host Secrets: Vault self-host CDN: Cloudflare Observ.: Grafana LGTM + Sentry + OpenTelemetry Contact: Form de demo (CTA único) · sem chat ao vivo no MVP Anti-spam: hCaptcha/Turnstile · Throttler 5/h por email Lang: pt-BR only no MVP · i18n-ready · sem hreflang até ativar en SEO técnico: Lighthouse >90 mobile · JSON-LD · sitemap · noindex /app/ Maintenance: Julian (solo founder mode) até 1º cliente; depois +1-2 devs ───────────────────────────────────────────────────────── ``` ### 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).**