# Design Log **Project:** SAR — Força de Vendas **Started:** 2026-05-26 **Method:** Whiteport Design Studio (WDS) --- ## Backlog > Business-value items. Add links to detail files if needed. - [ ] Complete product brief — Phase 1 (`A-Product-Brief/`) - [ ] Define trigger map — Phase 2 (`B-Trigger-Map/`) — 3 personas hipotéticas: rep externo, supervisor, admin - [ ] Create user scenarios — Phase 3 (`C-UX-Scenarios/`) - [ ] Page specifications — Phase 4 (`C-UX-Scenarios///`) - [ ] Design System overlay sobre AntD 6.4 — Phase 6 (`D-Design-System/`) - [ ] Agentic development — Phase 5 (`E-Development/`) --- ## Current | Task | Started | Agent | |------|---------|-------| | Phase 0 setup | 2026-05-26 | wds-0-project-setup | **Rules:** Mark what you start. Complete it when done (move to Log). One task at a time per agent. --- ## Design Loop Status > Per-page design progress. Updated by agents at every design transition. | Scenario | Step | Page | Status | Updated | |----------|------|------|--------|---------| **Status values:** `discussed` → `wireframed` → `specified` → `explored` → `building` → `built` → `approved` | `removed` --- ## Log ### 2026-05-26 — Project initialized (Phase 0) - Type: greenfield - Complexity: complex (Web Application, SaaS B2B multi-tenant) - Tech stack: STACK.md JCS v2.2 — React 19.2 + Vite 8 + Ant Design 6.4 / NestJS 11.1 + Prisma 7 + PostgreSQL 18 / Proxmox on-prem - Existing materials: `brand.md`, `STACK.md`, `CODING-RULES.md`, logos em `frontend/img/` - Strategic analysis: full (Phase 2 habilitada) - Brief level: complete - Stakes: small-business (JCS Sistemas) - Active agents: Saga (estratégia), Freya (design) - **Next:** `skill:wds-1-project-brief` com Saga ### 2026-05-26 — Phase 1 Steps 1, 1a, 2 concluídos - **Step 1 (Init):** materiais adicionais identificados — mockup SPA legado (`index.html` 2251 linhas, 9 telas, login excluído). - **Step 1a (Client Profile):** JCS = PME software house 11-50p, tech maturity alta + design iniciante. Julian acumula PO + Tech Lead + único Champion, autonomia total. Cultura fast-individual. SAR é upgrade-de-tier para SaaS web vendável (não conserto de legado). - **Step 2 (Vision):** SAR oferece 3 experiências distintas (rep operacional / supervisor tático / dono estratégico+IA). 6 diferenciais explícitos: inteligência de carteira, WhatsApp nativo, metas gamificadas, camadas por papel, IA estratégica, SaaS web distribuível. ### 2026-05-26 — Phase 1 Step 3 (Positioning) concluído - **Target:** Distribuidoras / indústrias / RCAs / PMEs com 5-50 reps externos (sweet spot mid-SMB). - **Dor central:** Donos e supervisores decidem no escuro — falta visibilidade em tempo real do que acontece na rua. - **Concorrência:** Apps verticais (Mercos/Promosoft/MaxFV/Workforce/Mobits), módulos de ERP (TOTVS/Sankhya/Senior), stack improvisado (Excel+WhatsApp+ERP), apps caseiros. - **Estratégia:** Coexistência com ERPs (não migração total) — multi-tenancy BD-por-workspace facilita integração heterogênea. WhatsApp+IA no MVP, não em roadmap. - **Próximo:** Step 5 — Business Model. ### 2026-05-26 — Phase 1 Step 5 (Business Model) concluído - **Modelo:** B2B SaaS per-seat, sales-led, trial 14-30 dias, contrato híbrido mensal/anual. - **Ticket médio:** R$ 750-7.500/mês (porte pequeno a médio alto). - **Implicações técnicas:** active rep counter no produto; provisioning automatizado de workspace para trial; billing suporta cobrança mensal recorrente + anual única; reusa BD-por-workspace (ADR 0006) para sandbox. - **Implicações marketing:** CTA "Agende demo", trial gated por SDR, pricing page no site. - **Próximo:** Step 6 — Business Customers. ### 2026-05-26 — Phase 1 Step 6 (Business Customers) concluído - **Buyer persona:** "Dono Empresário B2B" — 35-60 anos, sócio-fundador, decide na fé+demo+boca-a-boca. - **Decisão:** dono OU diretor comercial. Influenciadores chave: supervisor + reps. **Ausentes: financeiro, TI, jurídico** (venda operacional-emocional). - **Canais:** indicação + SEO + feiras + parceiros (todos os 4 ativos). - **Ciclo:** 2-4 semanas (pequeno) → 2-4 meses (médio alto). - **Implicações chave:** site precisa 3 páginas por papel, comparativos diretos com concorrentes, demo-friendliness obrigatória, JCS precisa de CRM próprio (possível dogfood). - **Próximo:** Step 7 — Target Users (3 user personas: rep / supervisor / dono). ### 2026-05-26 — Phase 1 Step 7 (Target Users) concluído - **4 personas confirmados:** Rafael (Rep — PRIMÁRIA, mobile-first), Sandra (Supervisora), Daniel (Dono+IA), **Alice (Admin — nova)** com responsabilidade por campanhas/promoções, pautas e tributação. - **Decisão crítica de design:** mobile-first para Rafael, desktop-first para os outros 3. SAR são 2 paradigmas de UI no mesmo produto. - **Diferenciais reforçados:** editor de campanhas no-code (Alice), assistente ICMS-ST (Alice), auditoria de pautas (Alice+regulatório), comissão em tempo real (Rafael), IA explicável (Daniel). - **Insight de venda:** demo precisa brilhar para Sandra, vender para Daniel, encantar Rafael. Alice é benefício, não argumento. - **Próximo:** Step 7a — Product Concept. ### 2026-05-26 — Phase 1 Step 7a (Product Concept) concluído - **Concept canônico:** "SAR é uma plataforma de 4 cockpits especializados (Rep / Supervisor / Dono / Admin) compartilhando um dado único em tempo real, atravessado por WhatsApp nativo e IA contextual." - **Metáfora:** equipe de Fórmula 1 — cada papel tem seu próprio dashboard sobre o mesmo carro em telemetria real. - **4 princípios:** cada cockpit com UX/device próprios; tempo real (Socket.IO/SSE); WhatsApp+IA como fios horizontais; multi-tenancy BD-por-workspace. - **Tensões aceitas:** 4 paradigmas UX vs 1 responsivo; tempo real obrigatório; WhatsApp/IA pilares desde MVP. - **Implicação:** Phase 6 (Design System) deixa de ser opcional — tokens compartilhados + variantes por cockpit. - **Próximo:** Step 8 — Success Criteria. ### 2026-05-26 — Phase 1 Step 8 (Success Criteria) concluído - **North star MVP:** 1º cliente paga e renova nos primeiros 3 meses após go-live. - **Y1:** 10-20 clientes (conservador) · NPS donos > 50 · ARR R$ 200k-600k. - **Timeline:** MVP em 3-4 meses → cliente renova em mês 6-7 → 10 clientes pagantes em mês 12. - **Métricas em 4 camadas:** negócio JCS · cliente · comportamento usuário · qualidade técnica. - **Implicação:** instrumentação de produto (OTel/Grafana/analytics/NPS) no MVP, não em roadmap. - **Próximo:** Step 9 — Competitive Landscape. ### 2026-05-26 — Phase 1 Step 9 (Competitive Landscape) concluído - **5 grupos analisados:** apps verticais (Mercos+), ERPs com módulo (TOTVS+), stack improvisado, apps caseiros, **do-nothing** (50%+ dos prospects). - **5 unfair advantages estruturais:** 4 cockpits + multi-tenancy BD-por-workspace + stack moderna + IA estrutural + velocidade JCS. - **Posição alvo:** vendas-first + baixo atrito de implantação. - **Estratégia de venda:** demo ataca do-nothing primeiro (urgência), coexistência com ERPs para Grupo 2. - **Janela de mercado:** 2-3 anos para entrincheirar; velocidade MVP é decisão estratégica. - **Próximo:** Step 10 — Constraints. ### 2026-05-26 — Phase 1 Step 10 (Constraints) concluído - **Tensão estratégica flagueada:** concept ambicioso + 3-4 meses + **solo founder mode** não comportam concept completo no MVP. - **Resolução proposta:** MVP mínimo defensível = Rafael + Sandra completos + Daniel/Alice simplificados + WhatsApp básico (sem IA). IA + editor no-code entram pós-MVP. - **Premissa:** 1º cliente é referência/parceiro, aceita limitações; quando renova, Julian contrata 1-2 devs e completa. - **Constraints fixos:** STACK.md v2.2, brand.md, LGPD by design, Proxmox on-prem BR, multi-tenancy BD-por-workspace. - **Flexível:** providers (pagamento, IA, WhatsApp), analytics, dark mode. - **Próximo:** Step 10a — Platform Strategy. ### 2026-05-26 — Phase 1 Step 10a (Platform Strategy) concluído - **Plataforma primária:** Web SaaS (React SPA + Cloudflare + Nginx). - **Rafael:** **PWA mobile-first com foco iOS** (Android continua com app legado por enquanto). - **Sandra:** Desktop + PWA mobile-light. - **Daniel:** Desktop + iPad first-class. - **Alice:** Desktop-only. - **Coexistência:** Android legado intocado no MVP; pós-MVP adapta para consumir backend SAR; futuro avalia native iOS+Android sobre SAR. - **Offline:** Read + Write com sync (IndexedDB + Service Worker) para Rafael. - **Native features MVP:** Geolocation, Web Push, Share API, Notification API. Camera/File API pós-MVP. - **Acessibilidade:** WCAG AA desde MVP. - **Próximo:** Step 11 — Tone of Voice. ### 2026-05-26 — Phase 1 Step 11 (Tone of Voice) concluído - **5 atributos canônicos:** Direto · Profissional sem ser frio · Confiante · Específico · Empático nos momentos difíceis. - **Variações por cockpit:** Rafael (informal/curto), Sandra (decisivo), Daniel (executivo), Alice (técnico-preciso). - **Vocabulário canônico:** Cliente · Rep · Orçamento · Pedido · Faturado · Visita · Carteira · Inativo · Painel · Aprovação. - **Don'ts:** emoji em produção, caps lock erros, burocratês, anglicismos desnecessários, frases dúbias. - **Implicação:** vocabulário vira tokens i18n; Phase 6 inclui guia microcopy; prompt de IA generativa precisa carregar atributos + vocabulário. - **Próximo:** Step 12 — Create Product Brief (consolidação dos Steps 1-11 num documento canônico). ### 2026-05-26 — Phase 1 BLOCK A (Product Brief) CONCLUÍDO ✅ - **Brief canônico gerado:** `design-artifacts/A-Product-Brief/01-product-brief.md` - **14 steps concluídos** (1, 1a, 2, 3, 5, 6, 7, 7a, 8, 9, 10, 10a, 11, 12) - **Tempo decorrido:** ~2-3h em uma sessão - **Confirmação:** narrativa estratégica apresentada e confirmada sem ajustes - **Próximo:** Block B (Content & Language) — Steps 13-18. ### 2026-05-27 — Phase 1 BLOCK B (Content & Language) CONCLUÍDO ✅ - **Documento canônico gerado:** `design-artifacts/A-Product-Brief/02-content-language.md` - **7 steps concluídos** (13, 14, 15, 16, 17, 17a, 18) - **Personality:** "Consultor sênior brasileiro de vendas B2B" (5 atributos) - **Tone spectrums:** Formality 3 · Mood 2 · Complexity 3 · Energy 2 - **Languages:** pt-BR only no MVP, i18n-ready - **SEO:** 6 intents de keywords · sitemap robusto · structured data plan · page-keyword map top 10 - **Content Structure:** 10 princípios site + 11 princípios produto + 8 exclusões explícitas - **Content guidelines:** UI/Marketing/Info/Email/WhatsApp/IA + ownership + checklist 13 itens - **Próximo:** Block C (Visual Direction) — fast-track via brand.md. ### 2026-05-27 — Phase 1 Step 19 (Inspiration Workshop) concluído - **🌟 Insight estratégico:** "Não acho nada no mercado de identidade como inspirador — uma das coisas que nos trouxe para esse projeto" → **estética moderna é parte do diferencial fundacional do SAR**, adicionar como 6º unfair advantage no Brief. - **4 referências externas:** Apple iCloud · Linear · Stripe Dashboard · Notion (todas fora do setor B2B força de vendas BR, propositalmente). - **7 padrões destilados:** sidebar fixa + tipografia hierarquia + único accent JCS + densidade respirável + animações sutis + dark mode + empty states informativos. - **Referências por cockpit** mapeadas para alimentar Phase 4. - **Próximo:** Step 20 — Visual Init. ### 2026-05-27 — Phase 1 BLOCK C (Visual Direction) CONCLUÍDO ✅ - **Documento canônico:** `design-artifacts/A-Product-Brief/03-visual-direction.md` - **8 steps concluídos** (19, 20, 21, 22, 23, 24, 25, 26) - **Insight estratégico:** estética moderna é parte do diferencial fundacional do SAR (6º unfair advantage) - **Visual DNA:** Modern Flat + Minimal · JCS Blue mono + accents · Plus Jakarta Geometric Humanist · Clean/Confident/Specific/Serene/Modern · split hero + cockpits diferenciados · effects sutis · screenshots-only Apple-style - **Próximo:** Block D (Platform Requirements) — fast-track via STACK.md. ### 2026-05-27 — Phase 1 BLOCK D (Platform Requirements) CONCLUÍDO ✅ - **Documento canônico:** `design-artifacts/A-Product-Brief/04-platform-requirements.md` - **6 steps concluídos** (27, 28, 29, 30, 31, 32) — batched após Step 27 - **Tech Stack:** espelho de STACK.md v2.2 (Node 24 + Nest 11 + Prisma 7 + React 19 + AntD 6.4 + multi-tenant BD-por-workspace ADR 0006 + Proxmox on-prem ADR 0004) - **Integrações fechadas:** Iugu (pagamento) · Meta Cloud API oficial (WhatsApp) · PostHog self-host (analytics) - **Integração ABERTA:** IA generativa — abstração multi-provider (Vercel AI SDK/LiteLLM) com default temporário Anthropic Claude - **Contact strategy:** Form de demo como único CTA; sem chat ao vivo no MVP - **Multilingual:** pt-BR only, i18n-ready · Lighthouse > 90 como CI gate - **Maintenance:** solo founder mode até 1º cliente - **Próximo:** Block E (Wrap-up) — Steps 33-36. ### 2026-05-27 — Phase 1 BLOCK E (Wrap-up) CONCLUÍDO ✅ — PHASE 1 INTEIRA COMPLETA 🎉 **Steps concluídos:** 33 (Analyze), 34 (Summary), 35 (Update Design Log), 36 (Provide Activation Phase 2). **Handover document:** `design-artifacts/A-Product-Brief/00-handover-summary.md` **Artefatos canônicos finais (todos em `design-artifacts/A-Product-Brief/`):** - `00-handover-summary.md` ⭐ entrada para Phase 2 - `01-product-brief.md` ⭐ brief estratégico (Block A) - `02-content-language.md` (Block B) - `03-visual-direction.md` (Block C) - `04-platform-requirements.md` (Block D) - `dialog/` (16 documentos de histórico detalhado) **Tempo total Phase 1:** ~6-8 horas em 2 dias (2026-05-26 + 2026-05-27). **Steps completados:** 36/36 ✅ **Decisões abertas conscientemente:** - Provider de IA generativa (resolver pré-feature IA) - Preço per-seat exato (validar com primeiras vendas) - Setup fee, add-ons premium, contratações futuras, JCS team photos **Tensão estratégica documentada:** - Solo founder + 3-4 meses + concept ambicioso → MVP minimalista (Rafael+Sandra completos; Daniel+Alice simplificados; IA+editor no-code pós-MVP). **Próximo:** Phase 2 — Trigger Mapping (skill `wds-2-trigger-mapping` com Saga). 5 workshops sequenciais. Output em `design-artifacts/B-Trigger-Map/`. ### 2026-05-27 — Phase 2 (Trigger Mapping) CONCLUÍDA ✅ (Dream mode) - **7 documentos gerados** em `design-artifacts/B-Trigger-Map/`: - `00-trigger-map.md` (hub + mermaid diagram + síntese + priorização MVP) - `01-business-goals.md` (5 BGs refinados do Brief) - `personas/02-rafael-representante.md` (PRIMARY MVP) - `personas/03-sandra-supervisora.md` (influenciadora compra) - `personas/04-daniel-dono.md` (IA + buyer overlap) - `personas/05-alice-admin.md` (operacional) - `06-feature-impact-analysis.md` (matrix Features × Forças × Personas) - **Session log:** `_progress/agent-experiences/2026-05-27-trigger-map-D.md` - **Modo:** Dream (autonomous) com self-review - **Tempo total:** ~15-20 min de geração - **5 business goals canônicos:** BG-1 PMF · BG-2 Referenciabilidade · BG-3 Modernidade · BG-4 Coexistência ERPs · BG-5 Fundação técnica - **Driving forces por persona:** 5-7 por persona, mix positivo+negativo, scored Freq×Int×Fit - **Tensões críticas resolvidas:** R-7↔S+6 (vigia↔talento) · D+4↔D-6 (IA↔black-box) · Sandra ops↔Daniel estratégico · concept↔solo founder - **Priorização MVP fechada:** P0 (lançamento offline, multi-tenant, real-time, 0 pedidos perdidos) → MVP core → MVP-light → pós-MVP - **Próximo:** Phase 3 — UX Scenarios (skill `wds-3-scenarios`). ### 2026-05-27 — Phase 3 pausada em Step 2 (decisão estratégica de paralelizar com setup) - **Step 1+2 concluídos:** site type = Mixed, 65 páginas inventariadas, **7 scenarios MVP aprovados** (Marketing→Demo · Trial Onboarding · 4 cockpits · Cross-cockpit Real-Time Flow) - **Decisão pragmática (escolha Julian):** pausar detalhamento dos outlines em Phase 3 e **começar setup do monorepo HOJE em paralelo**. Phase 4 page specs serão feitas just-in-time por feature, junto com o PR de implementação. - **Outlines Phase 3 detalhados (Steps 5+):** retomar quando primeiro cockpit precisar ser implementado. - **Próximo:** **Setup do monorepo SAR** — pnpm + Nx + Nest + Prisma + Vite + React + Docker Compose + git Gitea. ### 2026-05-27 — Setup do monorepo SAR CONCLUÍDO ✅ (Fases 1-9) - **Commit inicial:** `17c08e6 chore: initial monorepo scaffold + WDS Phase 1+2 artifacts` (3.631 arquivos, local, sem push) - **Stack ativa:** pnpm 11.1.0 · Node 24.15.0 · Nx 22.7.4 · TypeScript 5.9.3 · Prettier 3.8.3 - **5 projetos Nx:** api · api-e2e · web · web-e2e · api-interface - **Build geral:** ✅ todos os 3 projetos buildáveis passam - **Docker Compose dev** criado (Postgres 18 · Valkey 8 · MinIO · Mailpit) — não iniciado ainda - **`.env.example`** template completo com todas as variáveis críticas - **README.md + AGENTS.md** criados como entrada para devs/agentes - **Git remote:** `https://git.jcsinformatica.com.br/Julian/sar` configurado (push diferido) - **Próximos passos sugeridos:** 1. Criar repo no Gitea e fazer push (`git push -u origin main`) 2. Subir Docker Compose dev (`pnpm dev:up`) 3. Implementar master-login stub (auth real virá depois) 4. Implementar multi-tenant BD-por-workspace via Prisma factory + cls 5. Primeira tela viva: login + painel Rafael (vazio) ### 2026-05-27 — Foundation API (Frente A) CONCLUÍDA ✅ - **10 tarefas executadas (A1-A10):** tsconfig hardening · tracing stub · Zod env · Pino+redact LGPD · main.ts hardening · RFC 9457 filter · health endpoints · CLS workspace · /api/v1/ping · build+lint+smoke - **Estrutura `apps/api/src/`:** - `tracing.ts` — primeiro import (PGD-OBS-001), OTel SDK ativável por env - `main.ts` — helmet · CORS por env · compression · versionamento URI `/api/v1` · graceful shutdown · Pino logger global - `app/config/` — EnvSchema Zod 4 com `superRefine` (fail-fast prod, defaults dev) + EnvModule global - `app/logger/` — nestjs-pino com redact `*.cpf|*.cardNumber|*.password|authorization|cookie`, ignora `/health/*`, pretty em dev - `app/filters/problem-details.filter.ts` — RFC 9457 `application/problem+json`, Zod → 422 com array `errors`, type URIs em `https://docs.sar.jcs.com.br/errors/*` - `app/health/` — `/health/live` e `/health/ready` (skeleton, K=3 LRU pool placeholder documentado) - `app/workspace/` — ClsModule.forRootAsync com `setup` populando requestId+workspaceId; idGenerator alinha com pino-http (mesmo UUID header+body) - `app/ping/` — `GET /api/v1/ping` retornando status+service+version+workspaceId+requestId+uptime+now - `app.module.ts` — APP_PIPE: ZodValidationPipe (nestjs-zod) · APP_FILTER: ProblemDetailsFilter - **Dependências instaladas (root):** @nestjs/config 4.0 · @nestjs/terminus 11.1 · nestjs-pino 4.6 · pino 9.14 · pino-http 10.5 · pino-pretty 13.1 · nestjs-zod 4.3 · nestjs-cls 5.4 · helmet 8.2 · compression 1.8 · zod (catalog) · @types/express · @types/compression - **Smoke test verde:** `GET /api/v1/ping` → 200 com workspaceId+requestId · `/health/live` + `/health/ready` → 200 (heap OK) · `/api/v1/nope` → 404 application/problem+json · CORS preflight: localhost:4200 permitido, evil.com bloqueado · helmet headers todos presentes (HSTS, X-CTO, X-Frame-Options, etc.) · `x-request-id` propagado em todas as responses - **Hello-world boilerplate removido** (app.controller/service/specs) - **Pendente próxima sessão:** 1. **Frente C — Zod contracts compartilhados** (`libs/shared/api-interface`): primeiro DTO real (createZodDto) consumido por API + Web 2. **Frente D — ESLint boundaries** (3 tags Nx canônicas) + Husky+gitleaks 3. **Web → API integração:** `apps/web` chamar `/api/v1/ping` via TanStack Query (validar fundação ponta-a-ponta no browser) 4. **OpenTelemetry SDK** plugar quando entrar em catálogo (stub atual mantém posição correta) 5. **Master-login + WorkspacePrismaPool** (próxima frente arquitetural pesada) 6. **Docker compose dev**: subir e validar healthcheck (`pnpm dev:up`) ### 2026-05-27 — Foundation Web (Frente B) CONCLUÍDA ✅ - **Commit:** `3a42723 feat(web): foundation com brand JCS + AntD theme + Rafael painel placeholder` - **Tokens CSS** em `apps/web/src/styles/tokens.css` espelhando brand.md (paleta, tipografia, layout, motion, spacing, type scale) - **Plus Jakarta Sans Variable** self-host via `@fontsource-variable/plus-jakarta-sans` (LGPD + performance) - **AntD ConfigProvider tema JCS** em `apps/web/src/lib/theme.ts` — colorPrimary #004a99, radius 12/20, sombra canon, motion sutil - **TanStack Query + Router** setup com defaults conservadores (no refetchOnFocus, retry 5xx, no mutation retry — Idempotency-Key cobre) - **Layout shell:** Topbar 80px + Sidebar 260px com 9 itens cockpit Rafael (FA outline icons) - **RafaelPainel placeholder** com copy canônica + mock data: - "Bom dia, Rafael" + agenda do dia - Meta de maio (R$ 47.600 / R$ 60.000 = 79%) com Progress JCS Blue - "Pedidos no mês" (28, +18% vs abril) · "Comissão" (R$ 2.540, FLEX R$ 380) - "Clientes esfriando" — OPENFRIOS 47 dias, etc. — vocabulário canon - "Próxima visita" OPENFRIOS 14:30 - **Build OK:** 878KB JS (~250KB gzip) — vai code-splitar quando cockpits virarem rotas separadas - **Dev server:** http://localhost:4200/ servindo com title, theme-color, lang pt-BR corretos - **Pendentes próxima sessão:** Frente A (API foundation), C (Zod contracts), D (ESLint+boundaries), Docker permissions, **abrir browser e validar visualmente** ### 2026-05-27 — Frente C (Zod contracts shared) + Docker dev healthy CONCLUÍDA ✅ - **Escopo da sessão:** 1+2 do roadmap pendente — subir compose dev + criar primeiro contrato Zod compartilhado API↔Web. - **`libs/shared/api-interface/` reescrita:** - `src/lib/ping.contract.ts` — `PingResponseSchema` (z.object com `status: z.literal('ok')`, `requestId: z.uuid()`, `now: z.iso.datetime()`, etc.) + tipo inferido `PingResponse`. Comentário registra a decisão arquitetural abaixo. - `src/lib/ping.contract.spec.ts` — 6 testes vitest (1 happy + 5 rejeições: status, uuid, uptime negativo, datetime inválido, workspaceId vazio). - `src/index.ts` — reaponta para `ping.contract`. Placeholders `api-interface.{ts,spec.ts}` deletados. - `package.json` — `+zod: catalog:` (sai do dependency-checks do Nx limpo). - **Decisão arquitetural — lib stays framework-free:** `createZodDto` (nestjs-zod) **NÃO** vai pra `@sar/api-interface`. A Web vai consumir essa mesma lib e não pode arrastar dependência de framework backend. A lib carrega só Zod schema + tipo `z.infer`; quando precisar de DTO-class pro pipe, fica na camada API (`apps/api`). Alinha com CODING-RULES §06 ("schema é o contrato; DTO é a classe que o expõe"). - **`apps/api/src/app/ping/ping.controller.ts`** — `import type { PingResponse } from '@sar/api-interface'`, interface inline removida. Comportamento idêntico (CLS, uptime, version). - **Validação:** `nx run-many -t lint build -p api,api-interface` ✅ · `nx run api-interface:test` 6/6 ✅. - **Pegadinha Postgres 18+ encontrada e fixada (canon JCS):** - `pnpm dev:up` deu container `sar-postgres Restarting (1)` com erro "in 18+, these Docker images are configured to store database data in a format which is compatible with pg_ctlcluster (specifically, using major-version-specific directory names). Counter to that, there appears to be PostgreSQL data in: /var/lib/postgresql/data (unused mount/volume)". - Causa: Postgres 18+ mudou o layout do mount canônico de `/var/lib/postgresql/data` para `/var/lib/postgresql` (dados em subdir `18/main`) para suportar `pg_upgrade --link` sem boundary issues. Ref: `docker-library/postgres#1259`. - Fix: `docker-compose.dev.yml` postgres.volumes → `- sar-postgres-data:/var/lib/postgresql`. Comentário inline explicando o porquê. - Volume `sar-postgres-data` removido (`docker volume rm`) e compose religado limpo. Sem perda de dados (era primeiro boot). - **Pegadinha permissão Docker (registro pra próximas máquinas dev):** - Usuário fora do grupo `docker` → `permission denied` no `/var/run/docker.sock`. Fix: `sudo usermod -aG docker $USER` + `newgrp docker` (efeito imediato na sub-shell) ou logout/login para fixar em todos terminais novos. Aceitável em desktop dev pessoal; em servidor compartilhado, **não** (grupo docker ≡ root local). - **Stack dev validada healthy:** - `sar-postgres` (18-alpine) 5432 ✅ — BDs `sar_master` + `sar_workspace_dev`, extensions `pgcrypto`+`uuid-ossp` no workspace e `pgcrypto`+`plpgsql` no master. - `sar-valkey` (8-alpine) 6379 ✅ — `+PONG`. - `sar-minio` (latest) 9000+9001 ✅ — `/minio/health/live` HTTP 200; console UI em http://localhost:9001. - `sar-mailpit` (latest) 1025+8025 ✅ — web UI em http://localhost:8025. - **Pendente próxima sessão (em ordem recomendada):** 1. **Web→API integração ponta-a-ponta** — `apps/web` chama `/api/v1/ping` via TanStack Query + `PingResponseSchema.parse(...)` na response. Fecha o loop B+C; prova que o contrato Zod funciona dos dois lados. 2. **Frente D — ESLint boundaries** (tags Nx `scope:* · type:* · domain:*`) + Husky + gitleaks. 3. **Phase 3 WDS — PRD** via `/bmad-prd create` antes de qualquer modelagem de domínio. 4. **Master-login stub + WorkspacePrismaPool** (frente arquitetural pesada — depende de #3). 5. **OpenTelemetry SDK** plugar quando entrar em catálogo (stub atual mantém posição). ### 2026-05-27 — Web→API ponta-a-ponta (loop B+C fechado) CONCLUÍDO ✅ - **Escopo da sessão:** Pendência #1 do roadmap — provar que `@sar/api-interface` é honrado pelos dois lados em runtime, não só em build time. Loop B (Web foundation) + C (Zod contracts) fechado. - **Arquivos novos:** - `apps/web/src/lib/api-client.ts` — fetch wrapper que parseia `application/problem+json` (RFC 9457) em `ApiError` estruturado carregando status+type+title+detail+requestId+errors[]. Sem validação Zod aqui — responsabilidade do caller (CODING-RULES §05). - `apps/web/src/lib/queries/ping.ts` — `useApiPing()` TanStack Query chamando `/api/v1/ping` + `PingResponseSchema.parse(...)`. Drift servidor falha alto **antes** de chegar nos componentes. `refetchInterval: 30s` (Visual DNA "sereno"). - `apps/web/src/components/layout/FoundationStatus.tsx` — pill discreto na Topbar (verde/vermelho/cinza) com Tooltip detalhando service+version+workspaceId+requestId+uptime. Pulse `processing` no refetch silencioso. Conscientemente temporário — quando produto entrar em normal, vira indicador só em `/health`. - **Modificados:** - `apps/web/vite.config.mts` — `server.proxy['/api']: http://localhost:3000`. Evita CORS em dev e mantém URL relativa no código da Web; em produção, Nginx roteia mesmo origin. `changeOrigin: false` (mesma host). - `apps/web/src/components/layout/Topbar.tsx` — `` antes do sino. - **Validação ponta-a-ponta:** - `nx run web:lint` ✅ · `nx run web:build` ✅ (821ms, 309KB gzip) - `curl :4200/api/v1/ping` via proxy Vite → `200 application/json` com payload contratual completo (`status=ok`, `workspaceId=dev-workspace`, `requestId`, `uptimeSeconds=144`, `now`) - `curl :4200/api/v1/nope` → `404 application/problem+json` com `type/title/detail/instance/requestId` — prova que `ApiError` captura erro estruturado quando servidor falhar - Headers helmet, x-request-id, CORS expose-headers passam pelo proxy intactos - **Decisão arquitetural confirmada:** Web consome lib `@sar/api-interface` sem arrastar nada do Nest. `PingResponseSchema` viaja como Zod puro; `ApiError` na Web não conhece `HttpException` do Nest — só o contrato HTTP+JSON. Alinhamento com regra "lib stays framework-free" da sessão anterior. - **Pegadinhas notadas (não bloquearam):** - `_sidebarOpen` no AppShell ainda tem `eslint-disable` — fica pra Frente D ou primeiro responsivo mobile. - Bundle Web 976KB (309KB gzip) — code-splitting esperado quando rotas de cockpit virarem separadas (TanStack Router suporta nativo). Não age agora. - **Pendente próxima sessão (ordem atualizada):** 1. **Frente D — ESLint boundaries** (tags Nx `scope:* · type:* · domain:*`) + Husky + gitleaks. Higiene de PR antes de feature pesada. 2. **PRD WDS** via `/bmad-prd create` antes de modelar domínio. 3. **Master-login stub + WorkspacePrismaPool** (frente arquitetural — depende do PRD). 4. **OpenTelemetry SDK** plugar quando entrar no catálogo. ### 2026-05-27 — Frente D (ESLint boundaries + Husky + commitlint + gitleaks) CONCLUÍDA ✅ - **Escopo da sessão:** Higiene de PR — guardrails de qualidade antes da primeira feature de domínio. - **D1 — Tags Nx + depConstraints:** - Tags `scope:api|web|shared`, `type:app|e2e|util`, `domain:shared` adicionadas em todos os 5 projetos (e2e estavam vazios). - `eslint.config.mjs` depConstraints substituído por regras explícitas em 3 eixos: - `scope`: api só usa api+shared; web só usa web+shared; shared não importa código de app-scope. - `type`: apps dependem só de libs (feature/util/data); e2e só do seu app-par + utils; utils são folha. - `nx run-many --skip-nx-cache` verde em todos os 3 projetos com as novas regras. - **D2 — Husky + lint-staged:** - `husky 9` + `lint-staged 17` instalados. `prepare: "husky"` no `package.json`. - `pre-commit`: `eslint --max-warnings=0` + `prettier --check` só nos arquivos staged (rápido, sem varrer repo inteiro). - **D3 — commitlint:** - `@commitlint/cli` + `@commitlint/config-conventional` instalados. - `commitlint.config.js`: tipo obrigatório, subject lowercase, scope enum como `warn` (não `error` — permite escopos novos sem bloquear), body/footer ilimitados. - Hook `commit-msg` ativo. Smoke test: mensagem inválida → 2 erros; mensagem válida → pass. - **D4 — gitleaks via Docker:** - `.gitleaks.toml` criado com `useDefault = true` + allowlist para `.agents/`, `.claude/`, `tmp/`, `.env.example`, `pnpm-lock.yaml`. - Iteração em 3 rodadas para zerar falsos positivos: (1) JWTs de exemplo em BMad skills → excluir `.agents/` e `.claude/`; (2) `tmp/gitleaks-report.json` autopoluindo scan → excluir `tmp/` + adicionar ao `.gitignore`; (3) zero leaks no tree completo. - Pre-commit roda via `docker run --rm -v ... zricethezav/gitleaks:latest`; fallback silencioso se Docker indisponível (socket sem permissão no contexto do hook — comportamento correto; CI usa binário nativo). - **Pegadinha do commit-msg:** subject-case do commitlint rejeita "F" maiúsculo em "Frente D" — subject deve ser lowercase. Corrigido na mensagem de commit. - **Pegadinha Docker no hook:** `sg docker` não funciona em hooks não-interativos. Solução: fallback com `echo` + warning, e usar `sudo usermod -aG docker $USER` + logout/login para resolver permanentemente no desktop dev. - **Pendente próxima sessão (ordem atualizada):** 1. **PRD WDS** via `/bmad-prd create` antes de modelar qualquer domínio. Desbloqueia master-login + WorkspacePrismaPool. 2. **Master-login stub + WorkspacePrismaPool** (frente arquitetural pesada — depende do PRD). 3. **OpenTelemetry SDK** plugar quando entrar no catálogo. ### 2026-05-27 — PRD MVP FINALIZADO ✅ (`status: final`) - **Workspace:** `_bmad-output/planning-artifacts/prds/prd-sar-2026-05-27/` - **Artefatos:** `prd.md` (final) + `.decision-log.md` (8 decisões registradas) - **Working mode:** Fast Path — Julian definiu escopo em uma frase; documentos Phase 1+2 foram fonte de verdade via extração por subagentes. - **Escopo MVP fechado:** 9 capacidades (C1–C9) · 45 FRs · 3 jornadas de usuário · 6 NFRs — cockpits Rafael + Sandra. - **Cockpits fora do MVP:** Daniel e Alice → telas placeholder apenas. - **Decisões chave:** - WhatsApp = Share API nativa (sem Meta Cloud API no MVP) - ERP = importação manual (CSV/JSON); sem integração automática - Aprovação de desconto inclusa no MVP (confirmado explicitamente) - Limite de crédito numérico e inadimplência requerem conexão (não cacheados offline) - Falha de sync: Pedido retorna com status `falha de sync` + motivo; nunca descartado silenciosamente - **OQs abertas (6):** OQ-1/OQ-4 são phase-blockers para C2/C4 — dependem do primeiro cliente. OQ-3/OQ-6 são non-blockers. - **Reviewer gate:** 1 revisor subagente — veredito "Aprovado com Ressalvas"; 3 achados incorporados antes do `final`. - **Pendente próxima sessão (ordem atualizada):** 1. **OpenTelemetry SDK** plugar quando entrar no catálogo. 2. **Design C2/C4** (Consulta de Clientes + Lançamento de Pedido) — após resolver OQ-1 e OQ-4 com o primeiro cliente. ### 2026-05-27 — Master-login stub + WorkspacePrismaPool COMPLETO ✅ **Entregas (M1–M7):** - **M1 — Prisma 7 config corrigida:** `prisma.config.ts` usa `datasource.url` (não `migrate.adapter`) — API correta do Prisma 7. `prisma migrate dev` e `prisma generate` funcionando. Schema vazio (modelos virão com C2/C3). - **M2 — WorkspacePrismaPool:** LRU cache (max 10) de `PrismaClient` por `workspaceId`. `getOrCreate(workspaceId, dbUrl)`, `health(k=3)`, `onModuleDestroy`. Usa `@prisma/adapter-pg` + `pg.Pool` por workspace (ADR 0006). - **M3 — JwtAuthGuard:** Guard global (`APP_GUARD`) com `jose` HS256. Valida Bearer token, popula `req.user` com `{sub, workspace_id, role}`. Atualiza CLS com `workspaceId`, `userId` e `prisma` após validação. `@Public()` decorator para ping/health/dev-auth. - **M4 — Auth dev stub:** `POST /api/v1/auth/dev/token` — emite JWT HS256 com claims `{sub, workspace_id, role}`. Retorna 404 em produção. Contrato `DevTokenRequestSchema` + `AuthTokenResponseSchema` em `@sar/api-interface`. - **M5 — WorkspaceModule:** CLS setup simplificado (middleware só define `requestId` + `workspaceId` default). Guard sobrescreve workspace real do JWT. Pool não injetado no middleware (limitação do nestjs-cls `ClsRootModule`). - **M6 — Health ready:** `WorkspacePoolHealthIndicator` adicionado ao `/health/ready`. Amostra top-3 LRU — nunca O(N). `active: 0` quando nenhum workspace criado ainda. - **M7 — Smoke test:** API sobe limpo. `/health/live` ✓, `/health/ready` ✓ (pool ativo=0), `/ping` público ✓, `POST /auth/dev/token` emite token com claims corretos. **Decisões técnicas:** - `@prisma/client-runtime-utils` adicionado como dependência direta no workspace root (pnpm isolated mode não o hoista automaticamente). - Guard atualiza CLS depois do middleware (ordem correta NestJS: middleware → guard → handler). - Pool não injetado no ClsRootAsync devido a limitação de DI do nestjs-cls; guard faz a resolução. **Pendente próxima sessão:** 1. **OpenTelemetry SDK** plugar quando entrar no catálogo. 2. **Modelagem C2** — modelo `Client` no Prisma schema + migração + endpoint `GET /clients`. Requer OQ-1/OQ-4 resolvidos com primeiro cliente. --- ## About This Folder - **This file** — Single source of truth for project progress - **agent-experiences/** — Compressed insights from design discussions (dated files) - **wds-project-outline.yaml** — Project configuration from Phase 0 setup **Do not modify `wds-project-outline.yaml`** — it is the source of truth for project configuration.