chore: initial monorepo scaffold + WDS Phase 1+2 artifacts
- Nx 22.7 monorepo (pnpm 11.1, TypeScript 5.9, Node 24) - apps/api: NestJS 11 (CJS conforme CODING-RULES.md PGD-DB-004) - apps/web: React 19 + Vite 8 (ESM) - libs/shared/api-interface: Zod contract base - Docker Compose dev: Postgres 18, Valkey 8, MinIO, Mailpit - WDS artifacts: - design-artifacts/A-Product-Brief/ (5 docs canônicos + 16 dialogs) - design-artifacts/B-Trigger-Map/ (hub + 4 personas + feature impact) - Stack canon: STACK.md v2.2 + CODING-RULES.md v2.0 + brand.md - AGENTS.md + README.md como entrada para devs/agentes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
169
design-artifacts/A-Product-Brief/dialog/platform-strategy.md
Normal file
169
design-artifacts/A-Product-Brief/dialog/platform-strategy.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# 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 | `<input type="file" capture>` | 🟡 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
|
||||
Reference in New Issue
Block a user