# HANDOFF — Estado do Projeto Documento para a equipe que vai continuar o desenvolvimento. --- ## ✅ O que está pronto e funcionando ### Frontend (app/diario-bordo.html) Arquivo único HTML standalone (~200 KB). Pode ser: - Aberto direto no navegador - Servido pelo backend (já é o caso — está em `server/public/index.html`) - "Instalado" no Android via "Adicionar à tela inicial" **Funcionalidades verificadas em desenvolvimento:** | Recurso | Status | Observações | |---------|--------|-------------| | Persistência local (localStorage + IndexedDB) | ✅ | Robusto | | Travessias / Reparos / Pendências CRUD | ✅ | Pronto | | GPS + rastreio + mapa | ✅ | Leaflet + OSM tiles | | Vigia de fundeio + alarme | ✅ | Web Audio + Vibration + Wake Lock | | Swing circle + auto-recentro | ✅ | Implementado mas pouco testado em campo | | Geofencing | ✅ | Apenas círculos (polígonos = futuro) | | Mídia (foto/áudio/vídeo) | ✅ | IndexedDB, com viewer e download | | Importar GPX | ✅ | Trk e Rte points | | Exportar GPX | ✅ | Por travessia | | Sync com nuvem | ✅ | Pull, push, auto-sync | | Webhooks diretos (Telegram, Discord) | ✅ | Sem servidor | | Compartilhamento de posição ao vivo | ✅ | Requer servidor | | Checklists customizáveis | ✅ | 5 templates pré-cadastrados | | Windy Point Forecast API | ✅ | Premium key + fallback Open-Meteo | | Modo economia de energia | ✅ | Battery API (Chrome only) | ### Backend (server/) Express + SQLite + Docker, deployável em Coolify ou qualquer VPS. | Recurso | Status | |---------|--------| | Auth via Bearer Token | ✅ | | Endpoints de sync | ✅ | | Upload/download de mídia | ✅ | | Vigia + dead-man switch | ✅ | | Notificações fan-out (6 canais) | ✅ | | Compartilhamento público com mapa | ✅ | | Migração de schema | ✅ Automática | | Health check | ✅ | | Cleanup de shares expirados | ✅ Diário | --- ## ✅ Pronto (recém-implementado) - **Audit log de ações sensíveis** (`server/src/db.js` + 6 endpoints instrumentados + `GET /api/audit`) - Nova tabela `audit_log (id, ts, action, entity, entity_id, summary, ip)` com índice em `ts DESC` - Funções `db.audit(action, entity, entityId, summary, ip)` e `db.recentAudit(limit)` - Eventos rastreados: `state_set`, `media_insert`, `media_delete`, `share_create`, `share_revoke`, `share_zones_update` - Endpoint `GET /api/audit?limit=N` (autenticado, max 500) pra consulta - Implementado pelo squad `shivao-melhoria` em 2026-04-27 (run 2026-04-27-131311 +audit step) - **Validação Zod nos endpoints autenticados** (`server/src/schemas/index.js` + middleware nos endpoints) - `POST /api/data`: schema permissivo `z.object({data: z.record(z.string(), z.unknown())})` — aceita qualquer estrutura de objeto, rejeita payload sem `data` ou não-objeto - `POST /api/share/:token/zones`: schema com até 100 zonas, cada uma com lat/lng/radius validados - 400 com top 5 issues do Zod em caso de falha - Implementado pelo squad `shivao-melhoria` em 2026-04-27 (run 2026-04-27-131311 +zod step) - **Tamanho de upload reduzido pra 50 MB** (`server/src/index.js` linha 83) - Multer agora retorna 413 (Payload Too Large) acima de 50MB - Implementado pelo squad `shivao-melhoria` em 2026-04-27 (run 2026-04-27-131311) - **Rate limiting** nos 3 endpoints públicos de share (`/api/share/:token/info`, `/api/share/:token/positions`, `/share/:token`) - 60 req/min/IP via `express-rate-limit` v8 — cobre auto-refresh 15s da tripulação com margem 15× - Aplicado em `server/src/index.js` linhas 38 (limiter), 262, 271, 279 (middleware) - Implementado pelo squad `shivao-melhoria` em 2026-04-27 (run 2026-04-27-124638) ## ⚠️ O que precisa ser feito antes de produção ### 🔴 Crítico (segurança) 1. **CORS** atualmente permissivo (`*`) — apropriado para single-tenant pessoal, mas se for evoluir para multi-usuário, precisa rever - **Status:** decisão consciente de manter `*` enquanto for single-tenant. Item documentado, não-acionável agora. ### 🟡 Importante (qualidade) 3. **Testes automatizados** — projeto não tem testes - Backend: vitest ou jest para os endpoints - Frontend: playwright para fluxos críticos (especialmente alarme e GPS) 4. **Tratamento de erros no frontend** - Várias chamadas async fazem `.catch(()=>{})` silenciosamente - Falhas de sync não são reportadas ao usuário 5. **Reconexão da vigia** após app dormir - Wake Lock pode falhar; GPS pode pausar quando tab inativo - Investigar Service Worker + Background Sync API 6. **Refatoração do frontend** - HTML monolítico tem ~3500 linhas - Considerar quebrar em módulos (mas mantendo single-file deployment) - Avaliar migrar para Vite + Vue/Svelte mantendo build single-file 7. **TypeScript no backend** - Hoje JavaScript puro com JSDoc - Migração para TS deixaria mais robusto ### 🟢 Bom ter 8. **Service Worker / PWA real** - Hoje usa apenas meta tags + "Adicionar à tela inicial" - Service Worker permitiria offline real, push notifications 9. **Backup automático para S3/Backblaze** - Hoje SQLite + filesystem em volume Coolify - Schedule de backup off-site 10. **Multi-usuário / multi-barco** - Hoje single-tenant (um BOAT_TOKEN) - Para escalar: introduzir users + boats + permissions 11. **Histórico de tracks de cada vigia de fundeio** - Hoje só salva resumo (max drift, alarms) - Salvar também a poligonal de movimento 12. **i18n** - Hoje hardcoded em português - Estrutura permite extrair strings facilmente --- ## 🐛 Bugs/limitações conhecidas 1. **iOS:** Battery API não disponível → modo "auto" sempre cai em normal. Não é problema crítico, só não economiza bateria automaticamente. 2. **iOS:** Wake Lock funciona em Safari 16.4+. Em versões anteriores, a tela apaga e o GPS pode parar. 3. **iOS:** Modo silencioso pode silenciar o som do alarme. Vibração continua funcionando. 4. **Android:** Quando o navegador é fechado completamente, o GPS pára (limitação do browser). O dead-man switch do servidor cobre isso. 5. **Modal de tracking** abre como modal mas seria melhor full-screen real. Atualmente usa CSS hack com height:100vh. 6. **Geofencing** só suporta círculos, não polígonos. Para áreas irregulares (canal estreito, baía com formato complexo) é uma limitação. 7. **Map tiles** vêm de tile.openstreetmap.org sem cache. Em viagem com dados móveis caros, pode consumir muito. Considerar cache ou tiles próprios (MapTiler, Mapbox). 8. **Não há sincronização incremental** — sempre envia/baixa o estado todo. Para usuários com muito histórico, fica lento. Sugerimos versionar por entidade (CRDT ou last-write-wins por id+ts). 9. **A chave Windy fica em localStorage** — se sincronizada via cloud, trafega entre dispositivos do dono (OK, mas vale documentar). 10. **Sem HTTPS local em desenvolvimento** — a API do Geolocation só funciona em HTTPS ou localhost. Devs precisam usar localhost. --- ## 📋 Decisões técnicas relevantes Detalhes em **ARCHITECTURE.md**, mas em resumo: - **SQLite + filesystem** em vez de Postgres + S3 → simplicidade, single-tenant, fácil backup - **Single-file HTML** → instalável no celular sem app store, deploy simples - **Bearer Token simples** em vez de OAuth → uso pessoal - **Leaflet + OSM** em vez de Google Maps/Mapbox → grátis, sem chaves - **Web Audio API** para alarme em vez de mp3 estático → mais alto e confiável - **Open-Meteo como fallback** → app funciona sem nenhuma chave de API - **Windy** como provedor premium → o dono já tem assinatura --- ## 🚀 Para começar Para colocar em produção: 1. Ver **DEPLOY.md** — passo-a-passo do Coolify 2. Configurar canais de notificação (mínimo: Telegram via .env) 3. Criar bot do Telegram + obter chat_id (instruções em DEPLOY.md) 4. Definir `BOAT_TOKEN` (32 chars aleatórios) 5. Volume `/data` persistente 6. Deploy Para desenvolver localmente: 1. Ver **CONTRIBUTING.md** 2. `cp .env.example .env` e preencher 3. `npm install` 4. `npm start` 5. Acessar `http://localhost:3000` Para o time do dono passar a chave Windy: - A chave premium é configurada **no app** (não no servidor) via Aba Arquivo → Meteorologia · Windy Point Forecast - Não cole no código nem em variáveis de ambiente --- ## 📞 Contato Projeto pessoal do dono do veleiro Shivao. Equipe de devs deve coordenar diretamente com ele para credenciais de produção, domínios e orçamento.