shivao-projeto/HANDOFF.md
PontualTech / Karlão 5b02feae50 chore: initial commit + security hardening (4 runs squad shivao-melhoria)
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>
2026-04-27 13:24:08 -03:00

8.4 KiB
Raw Blame History

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)

  1. Testes automatizados — projeto não tem testes

    • Backend: vitest ou jest para os endpoints
    • Frontend: playwright para fluxos críticos (especialmente alarme e GPS)
  2. Tratamento de erros no frontend

    • Várias chamadas async fazem .catch(()=>{}) silenciosamente
    • Falhas de sync não são reportadas ao usuário
  3. Reconexão da vigia após app dormir

    • Wake Lock pode falhar; GPS pode pausar quando tab inativo
    • Investigar Service Worker + Background Sync API
  4. 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
  5. TypeScript no backend

    • Hoje JavaScript puro com JSDoc
    • Migração para TS deixaria mais robusto

🟢 Bom ter

  1. Service Worker / PWA real

    • Hoje usa apenas meta tags + "Adicionar à tela inicial"
    • Service Worker permitiria offline real, push notifications
  2. Backup automático para S3/Backblaze

    • Hoje SQLite + filesystem em volume Coolify
    • Schedule de backup off-site
  3. Multi-usuário / multi-barco

    • Hoje single-tenant (um BOAT_TOKEN)
    • Para escalar: introduzir users + boats + permissions
  4. Histórico de tracks de cada vigia de fundeio

    • Hoje só salva resumo (max drift, alarms)
    • Salvar também a poligonal de movimento
  5. 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.