# 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 (parcialmente resolvido)**
   - ✅ Catch silencioso de `dispatchWebhooks` em zona PROIBIDA (linha 3280) agora loga + toast (run 2026-04-27-131311 +catch step)
   - Restantes: catches em fetches Windy/Open-Meteo (linhas 2712, 2733) — **fallbacks intencionais, mantidos conscientemente**
   - Restantes: catches `}catch(e){}` em Wake Lock e tracking state — **best effort em iOS antigo, mantidos**
   - Pendente futura: indicador visual de "última sync falhou" no painel cloud

5. **Reconexão da vigia (parcialmente resolvido)**
   - ✅ Wake Lock auto-reacquire: `wakeLock.addEventListener('release', ...)` em tracking + anchor (run 2026-04-27-131311 +reconnect step)
   - ✅ GPS retry exponencial (1s→2s→4s→8s→16s→30s) com `PERMISSION_DENIED` fatal sem retry, em tracking + anchor
   - ✅ `visibilitychange` listener (já existia) re-acquire Wake Lock quando tab volta foreground
   - Pendente: Service Worker real (para push notifications + offline tile cache) — exige spec própria, deixar pra futuro

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.
