# Platform Strategy — SAR (Força de Vendas) **Confirmed:** 2026-05-26 **Step:** 10a — Platform Strategy > Estratégia de plataforma decorre da STACK.md + Product Concept + Constraints. Esta sessão consolida e abre as decisões de **device strategy** que afetam o MVP. --- ## Plataforma primária — Web SaaS (decisão fixa via STACK.md) | Camada | Decisão | |---|---| | **Tipo** | Web SaaS multi-tenant | | **Frontend** | React 19.2 SPA via Vite 8 (Rolldown) | | **Distribuição** | Sem app store; deploy = rolling docker-compose em VMs Proxmox | | **CDN/edge** | Cloudflare + Nginx para SPA estática | | **Identidade** | master-login (IdP próprio) OAuth2/OIDC | | **Multi-tenancy** | BD-por-workspace; workspace resolvido por host/path | --- ## Device strategy por cockpit ### 🟢 Rafael (Rep) — **PWA mobile-first** | Aspecto | Decisão | |---|---| | **Tecnologia** | **Progressive Web App (PWA)** — SPA com Service Worker + Manifest + Web Push | | **Device-target primário** | **iOS** (gap no mercado; vocês não têm app native iOS) | | **Device-target secundário** | Android (usuários que preferem PWA ao app legado) | | **Instalação** | "Adicionar à Tela de Início" no iOS Safari / Android Chrome | | **Push** | Web Push API via Service Worker (notificações de pedido aprovado, alertas) | | **Offline** | **Read + Write com sync** (lançamento de pedido offline + reconciliação quando volta sinal) | | **Native features** | Geolocation (check-in) · Web Push · Share API (compartilhar pedido) | | **Dark mode** | Desejável (uso noturno em carro/posto) | ### 🟡 Sandra (Supervisora) — Web desktop + mobile-light | Aspecto | Decisão | |---|---| | **Device-target primário** | Desktop (notebook escritório) | | **Device-target secundário** | Mobile (PWA — consultas rápidas, aprovações via push) | | **Push** | Web Push para notificar aprovações pendentes | | **Layout** | Topbar 80px + Sidebar 260px (brand.md) com tabelas/listas densas | ### 🔵 Daniel (Dono) — Desktop + **iPad first-class** | Aspecto | Decisão | |---|---| | **Device-target primário** | Desktop/notebook | | **Device-target secundário** | **iPad first-class** — testes e ajustes dedicados | | **Layout** | Visualização-first (gráficos amplos), tom executivo | | **Modo** | Claro/escuro elegante (uso noturno em casa) | ### 🟣 Alice (Admin) — Desktop-only | Aspecto | Decisão | |---|---| | **Device-target** | Desktop apenas (sem investimento mobile/tablet) | | **Layout** | Dense forms com assistentes, bulk operations, auditoria visível | --- ## Coexistência com app Android legado ### Decisão estratégica - **MVP:** SAR PWA + backend SAR construídos do zero. **App Android legado continua intocado** no curto prazo. - **Pós-MVP (Y1+):** Iniciar **adaptação do app Android legado para consumir backend SAR**, unificando a fonte da verdade. - **Futuro (Y1-Y2):** Avaliar reescrita do app Android para mobile-native sobre backend SAR (possivelmente Capacitor wrap do PWA ou React Native). ### Modelo evolutivo ``` HOJE MVP Pós-MVP Futuro ──── ─── ─────── ────── Backend [App Android legado] [App Android legado] [App Android adapt.] [Native iOS] │ │ [SAR backend] ▲ [Native Android] │ │ │ │ │ [Backend [Backend ↓ ▼ ▼ legado] legado] [SAR PWA iOS] [SAR backend] [SAR backend] (único) (único) ``` ### Implicação técnica - **MVP:** SAR é greenfield, sem dependência do Android legado. Reps Android continuam no app legado se já o usam; clientes novos vão direto para SAR PWA. - **Pós-MVP:** App Android passa a consumir API SAR — necessária camada de compatibilidade temporária (provavelmente adapter no backend para mapear contratos antigos do app). --- ## Offline strategy detalhada (Rafael) ### Nível escolhido: **Read + Write com sync** | Operação | Online | Offline | |---|---|---| | Visualizar catálogo | API + cache | Cache local (IndexedDB) | | Visualizar clientes | API + cache | Cache local (clientes da carteira do rep) | | Visualizar últimos pedidos | API + cache | Cache local (últimos N) | | **Lançar pedido** | API + ack imediato | **IndexedDB queue + Service Worker sync** | | Editar pedido em rascunho | API + cache | IndexedDB | | Aprovação de desconto (Sandra) | Real-time | (Não aplicável — Sandra é desktop) | ### Implementação (a detalhar em Phase 3 / 4) - **Storage local:** IndexedDB para cache + queue de pendentes - **Sync layer:** Service Worker reage a `online` event; envia queue serialmente - **Conflict resolution:** Last-write-wins para rascunho; pedido finalizado é imutável depois de submeter - **UI signaling:** ícone de "modo offline" claro; toast quando sync completa; mostrar status do pedido (`enviando…` → `enviado`) - **Limites:** offline funciona por até X dias (configurável); depois força login + sync ### Risco a mitigar - **Pedido duplicado:** rep lança offline, depois online sem perceber sync, lança de novo. Solução: `Idempotency-Key` por pedido (UUID gerado local) — já é padrão STACK.md §05. - **Catálogo desatualizado:** rep lança pedido com preço/produto que mudou. Solução: validação no sync com `If-Match` ou status `requer_revisao` se preço divergiu. --- ## Native features do MVP | Feature | Cockpit | Web API | Status MVP | |---|---|---|---| | **Geolocation** (check-in agenda) | Rafael | `navigator.geolocation` + permissão | ✅ MVP | | **Web Push** (aprovação para Sandra; pedido aprovado para Rafael) | Sandra, Rafael | Push API + Service Worker | ✅ MVP (parte do PWA) | | **Share API** (Rafael compartilha pedido/orçamento via WhatsApp do celular) | Rafael | `navigator.share` | ✅ MVP | | **Notification API** (desktop) | Sandra | `Notification` | ✅ MVP | | **Camera** (foto documento/produto) | Rafael, Alice | `` | 🟡 Pós-MVP | | **File System Access** (Alice import CSV) | Alice | File System API + fallback | 🟡 Pós-MVP | ### Diferença: Share API vs WhatsApp integrado nativo do SAR - **Share API** (MVP): Rafael toca "Compartilhar pedido" → abre menu nativo do iOS/Android → cliente recebe link/PDF via WhatsApp do celular DELE - **WhatsApp nativo do SAR** (parcial no MVP): backend envia mensagem programática via WhatsApp Business API quando pedido é aprovado (notificação ao cliente final). Implementação Step 29. Os dois coexistem. Share API é "rep compartilha como pessoa", WhatsApp nativo é "produto envia em nome do cliente-empresa". --- ## Interaction models | Modelo | Cockpits | Notas | |---|---|---| | **Touch** | Rafael (primário), Sandra/Daniel/Alice (secundário) | Botões 44×44pt mínimo no Rafael | | **Mouse + teclado** | Sandra, Daniel, Alice | Atalhos de teclado avaliados em Phase 4 (especialmente Alice bulk ops) | | **Voice commands** | Nenhum no MVP | Possível futuro: Rafael ditando pedido enquanto dirige (risco de segurança rodoviária — descartado por enquanto) | | **Gesture** | Rafael (swipe entre clientes, pull-to-refresh) | Padrão mobile | | **Acessibilidade** | Todos | WCAG AA mínimo; screen reader compatível desde MVP | --- ## Implicações de design e desenvolvimento 1. **PWA exige Service Worker robusto** — não é "responsivo com manifest", é arquitetura cliente complexa. Investimento explícito de ~1-2 semanas no MVP. 2. **Web Push exige certificado VAPID + backend para envio** — encaixa com BullMQ jobs já previstos. 3. **Offline write exige UI com estados claros** — `enviando…` `enviado` `falha de sync` `aguardando reconexão` (estados visíveis ao Rafael). 4. **iPad first-class implica testes regulares em iPad Safari** durante Phase 4 — adicionar ao matriz de QA. 5. **Compatibilidade com Android legado é débito conhecido**, não esquecido — pós-MVP terá adapter layer ou contratos compartilhados. --- ## Lacunas conscientemente adiadas - Native iOS / native Android (Capacitor / React Native) — pós-Y1 - Voice commands para Rafael — descartado por segurança rodoviária - Acessibilidade avançada (WCAG AAA, switch controls) — manter WCAG AA no MVP - Camera e File System Access — pós-MVP - App Smartwatch para alertas Sandra — fora de escopo