Importação inicial do projeto Shivão (Diário de Bordo do veleiro) em estado pronto pra produção, já incluindo as 5 mudanças de hardening implementadas pela squad shivao-melhoria em 2026-04-27. Mudanças de hardening (HANDOFF.md seção "✅ Pronto"): 1. **Rate limiting nos 3 endpoints públicos de share** - express-rate-limit ^8.4.1, 60 req/min/IP - server/src/index.js linhas 38, 262, 271, 279 2. **Tamanho de upload reduzido pra 50MB** (era 200MB) - multer linha 84 3. **Validação Zod nos endpoints autenticados** (POST /api/data e /zones) - novo arquivo server/src/schemas/index.js - middleware validate() retorna 400 com top 5 issues 4. **Audit log de ações sensíveis** - nova tabela audit_log + funções db.audit() e db.recentAudit() - 6 endpoints instrumentados (state_set, media_insert/delete, share_create/revoke/zones_update) - novo endpoint GET /api/audit (autenticado) 5. **Catch silencioso de webhook em zona PROIBIDA tratado** - app/diario-bordo.html + server/public/index.html linha 3280 - agora loga erro + exibe toast ao usuário Status final do HANDOFF: - 🔴 Críticos restantes: 1 (CORS — decisão consciente single-tenant, não-acionável) - 🟡 Importantes: 4 itens (testes, vigia reconnect, refator frontend, demais catches) - 🟢 Bom-ter: 5 itens Stack: Node 20 ESM + Express + better-sqlite3 + Docker (Coolify) Single-tenant pessoal · single-file frontend HTML · offline-first Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.8 KiB
4.8 KiB
PROJECT_CONTEXT — Histórico e contexto
Documento informal sobre como o projeto chegou ao estado atual. Útil para a equipe entender as decisões e a evolução.
Origem
O projeto começou simples: o dono do veleiro Shivao queria um diário de bordo digital para registrar viagens, manutenções, horímetro do motor e passageiros, com possibilidade de exportar e compartilhar.
A primeira versão foi um HTML standalone com localStorage — funcional, mas limitado. A partir daí, foi crescendo iterativamente:
Linha do tempo
- v1: HTML básico — viagens, manutenções, exportar JSON/CSV
- v2: Adicionado uso no Android, fotos da câmera, áudio (MediaRecorder), vídeo, lembretes de manutenção futura, lista de manutenções a fazer com custos. Migrado armazenamento de mídia para IndexedDB.
- v3: GPS — detecção de posição inicial, rastreio em tempo real, cálculo de milhas náuticas e velocidade em nós, mapa Leaflet com OSM.
- v4 (design): Refatoração visual completa — adoção da estética "marítimo editorial" com Fraunces (serif itálico), Manrope, JetBrains Mono, paleta pergaminho/marinha/latão.
- v5: Vigia de fundeio com alarme sonoro forte, vibração, botões para disparar mensagens de WhatsApp/SMS/e-mail (limitação: browser não envia automaticamente, requer 1 toque por contato).
- v6: Servidor próprio (Node.js + SQLite + Docker para Coolify VPS) com sincronização na nuvem, dead-man switch, e fan-out automático de notificações para múltiplos canais (Telegram, ntfy, e-mail SMTP, Twilio, webhook).
- v7: Webhooks diretos do app (Telegram, Discord, genérico) sem precisar do servidor; histórico de fundeios com mapa de cada sessão; compensação de maré/corrente via "swing circle" (centro de giro independente da posição da âncora) com auto-recentro.
- v8: Geofencing com zonas de proibição/atenção; compartilhamento público de posição em tempo real (link temporário com mapa Leaflet); importação de tracks GPX.
- v9: Exportação GPX por viagem; modo economia de energia (Battery API); previsão meteorológica (Open-Meteo); checklists de bordo customizáveis.
- v10 (atual): Migração da meteorologia para Windy Point Forecast API
(premium key do dono) com cálculo de vento a partir de componentes
wind_u/wind_ve ondas em modelogfsWaveparalelo. Open-Meteo mantido como fallback.
Princípios mantidos durante a evolução
- Single-tenant: o app é pessoal, do dono. Sem necessidade de gestão de usuários, login complexo, etc.
- Offline-first: o app funciona 100% sem o servidor. O servidor é uma camada de robustez, não dependência.
- Single-file frontend: facilita distribuição, instalação no celular e uso offline.
- Single binary backend: 1 container Docker, 1 banco SQLite, 1 volume. Deploy trivial no Coolify.
- Estética cuidada: o app não é um "app de app store qualquer" — tem identidade visual própria, faz sentido para um barco de verdade.
- Sem dark patterns: zero analytics, zero tracking, zero ads. Tudo do dono fica no servidor do dono.
O que NÃO foi feito por opção
- Login/registro de usuários: por ser single-tenant pessoal.
- App nativo iOS/Android: maior complexidade, sem ganho proporcional para uso pessoal. PWA atende.
- Service Worker: ficou como TODO. App funciona offline-first mas não é PWA full ainda.
- Push notifications via FCM: para o uso anchor watch, polling com heartbeat é melhor. Para outros casos, ntfy resolve.
- TypeScript: por simplicidade. Equipe pode migrar se quiser.
- Build step: para manter o "1 arquivo HTML" como deliverável principal.
Limitações conhecidas e aceitas
(coisas que conscientemente deixamos como estão)
- Frontend monolítico em um único arquivo HTML
- API do servidor sobrescreve estado (não merge — vence o último write)
- Mensagens automáticas SMS/WhatsApp dependem do servidor (Twilio pago) ou do tap manual do usuário no celular
- iOS tem limitações em algumas APIs (Battery, alguns modos de áudio com silencioso ativado)
Para o time de devs
O dono está confortável em deixar vocês continuarem a evolução. Pontos importantes:
- Não compliquem prematuramente. O app funciona. Adicione complexidade só quando ela se justifica.
- Mantenham a estética. A identidade visual é parte da experiência.
- Test em condições reais. Bateria fraca, sinal fraco, sol forte, mãos molhadas — esses são os cenários reais.
- Coordenem com o dono antes de mudanças grandes (refatorações, mudanças de stack, novos custos recorrentes).
- Backups são sagrados. Antes de qualquer mudança no schema, garantir que os dados existentes do dono não se perdem.
Boa sorte! 🌊⛵