obsidian-vault/ligbox-ops-platform/specs/007-mobile-push-notifications/spec.md
2026-06-19 17:26:42 +00:00

269 lines
8.8 KiB
Markdown

# Feature Specification: Push Mobile & Web — Ligbox Ops (007)
**Criado:** 2026-06-10
**Solicitado por:** Roger
**Status:** 📋 **Draft — pronta para plano**
**Prioridade:** P1
**Depende de:** Spec 003 (auth), Spec 004 (contas / ntfy OTP)
**API alvo:** `0.9.0-desk-push` (futuro)
---
## Resumo
Sistema de **notificações push** para a equipe Ligbox Ops (técnicos, NOC, ops lead) a partir do **Ligbox Ops Desk** (`desk.ligbox.com.br`), complementando e-mail e UI web.
**Contexto atual (Spec 004):** push **ntfy** por tópico na ativação de conta (OTP). Usuário inscreve manualmente no app ntfy. Não há push integrado ao login nem alertas operacionais (tickets, Wazuh).
**Objetivo Spec 007:** evoluir para push **por usuário autenticado**, com eventos operacionais relevantes, começando pelo caminho mais simples e escalável.
---
## Decisões propostas (Roger — validar no plano)
| Ponto | Proposta MVP | Evolução |
|-------|--------------|----------|
| **Público** | Usuários Desk logados (`technician`, `noc`, `ops_lead`, `super_admin`) | Clientes finais — fora de escopo |
| **MVP Fase A** | **ntfy por usuário** — tópico único por `desk_users.username` + opt-in em Minha conta | Já temos infra parcial |
| **MVP Fase B** | **Web Push (PWA)** — Service Worker + VAPID no Desk | Android Chrome + iOS Safari 16.4+ |
| **App nativo** | Fora do MVP | FCM/APNs via React Native / Flutter |
| **Servidor push** | `ntfy.sh` público (Fase A) · VAPID self-hosted VM122 (Fase B) | FCM unificado depois |
| **Idioma** | pt-BR | — |
### Recomendação técnica (base Kimi + Ligbox)
| Cenário | Tecnologia | Quando usar |
|---------|------------|-------------|
| Equipe ops, web Desk | **ntfy + Web Push PWA** | **Agora** — baixo custo, sem app store |
| App nativo futuro | **Firebase Cloud Messaging (FCM)** | Se houver app RN/Flutter |
| WebView embrulhando site | Bridge nativo + FCM | Não recomendado |
**Por que não só ntfy:** Spec 004 usa tópico de ativação efêmero. Spec 007 amarra push ao **usuário logado** e dispara em eventos do Desk (ticket novo, Wazuh ≥10, pedido cadastro).
**Por que Web Push depois:** permite notificação mesmo sem app ntfy instalado, direto no browser (PWA instalado ou Safari iOS).
---
## Eventos push (prioridade)
| Evento | Quem recebe | Prioridade ntfy | Fase |
|--------|-------------|-----------------|------|
| Novo ticket Wazuh (level ≥10) | `noc`, `ops_lead`, `super_admin` | `high` | A |
| Novo pedido cadastro Desk | `super_admin` | `default` | A |
| Ticket atribuído a mim | usuário assignee | `default` | A |
| OTP ativação / senha | candidato (fluxo 004) | `high` | ✅ já existe |
| Funil onboarding travado | `ops_lead` | `low` | B |
| Audit scorecard crítico | `ops_lead` | `default` | B |
---
## Arquitetura alvo
```mermaid
flowchart LR
subgraph VM122
API[Ligbox Ops API]
SW[Service Worker PWA]
end
subgraph Clientes
WEB[Desk browser]
NTFY[App ntfy Android/iOS]
end
subgraph Push
NTFYS[ntfy.sh]
WEBPUSH[Web Push VAPID]
end
WEB --> API
WEB --> SW
API -->|POST tópico| NTFYS
API -->|sendNotification| WEBPUSH
NTFYS --> NTFY
WEBPUSH --> WEB
```
### Fluxo Fase A — ntfy por usuário
1. Usuário logado abre **Minha conta** → ativa push ntfy
2. API gera/recupera `ntfy_topic` estável: `ligbox-desk-{hash(username)}`
3. UI exibe link `https://ntfy.sh/{topic}` + QR para app ntfy
4. Backend grava `push_ntfy_enabled = 1` em `desk_users`
5. Em evento (ex.: ticket Wazuh), worker/API faz `POST ntfy.sh/{topic}`
### Fluxo Fase B — Web Push PWA
1. Usuário aceita permissão de notificação no browser
2. Service Worker registra `PushSubscription` (endpoint + keys)
3. Frontend envia subscription para `POST /api/v1/push/subscribe`
4. Backend persiste em `push_subscriptions`
5. Em evento, API envia via biblioteca `pywebpush` (VAPID)
---
## Data model (novo)
### `desk_users` (alteração)
| Campo | Tipo | Uso |
|-------|------|-----|
| `ntfy_topic` | TEXT | Tópico estável por usuário (migrar de só registration) |
| `push_ntfy_enabled` | INTEGER | 1 se opt-in ntfy |
| `push_web_enabled` | INTEGER | 1 se tem subscription Web Push ativa |
### `push_subscriptions` (nova)
```sql
CREATE TABLE push_subscriptions (
id INTEGER PRIMARY KEY,
username TEXT NOT NULL,
platform TEXT NOT NULL, -- 'webpush' | 'fcm' (futuro)
endpoint TEXT NOT NULL, -- URL Web Push ou FCM token
auth_keys TEXT, -- JSON: p256dh, auth (webpush)
user_agent TEXT,
created_at TEXT NOT NULL,
last_used_at TEXT,
active INTEGER NOT NULL DEFAULT 1,
UNIQUE(username, endpoint)
);
```
---
## API proposta (v0.9)
| Método | Endpoint | Auth | Descrição |
|--------|----------|------|-----------|
| GET | `/api/v1/push/settings` | JWT | Estado push do usuário + tópico ntfy |
| POST | `/api/v1/push/ntfy/enable` | JWT | Gera tópico + opt-in |
| POST | `/api/v1/push/ntfy/disable` | JWT | Opt-out |
| POST | `/api/v1/push/subscribe` | JWT | Registra Web Push subscription |
| DELETE | `/api/v1/push/subscribe/{id}` | JWT | Remove subscription |
| POST | `/api/v1/push/test` | JWT | Notificação teste (só próprio user) |
**Interno (worker / hooks):**
```python
push_service.notify_user(username, title, body, priority="default", url="/tickets/123")
push_service.notify_role("noc", title, body, ...)
```
---
## UI proposta
### Minha conta (extensão Spec 004)
Nova seção **Notificações push**:
| Bloco | Conteúdo |
|-------|----------|
| **ntfy (app)** | Toggle ativar · link tópico · QR · instruções Android/iOS |
| **Browser (PWA)** | Botão «Ativar notificações neste dispositivo» · status permissão |
| **Teste** | «Enviar notificação teste» |
### PWA mínimo
- `manifest.json` (nome, ícone, `start_url`, `display: standalone`)
- Service Worker `sw.js` — push + click abre URL do ticket
- Registro SW em `index.html` boot
---
## Comparativo de canais (referência Kimi)
| Canal | Android | iOS | Esforço | Custo Ligbox |
|-------|---------|-----|---------|--------------|
| **ntfy app** | ✅ | ✅ | Baixo | Grátis (`ntfy.sh`) |
| **Web Push PWA** | ✅ Chrome | ✅ Safari 16.4+ | Médio | Grátis (VAPID) |
| **FCM** | ✅ | ✅ | Alto (app/SDK) | Grátis |
| **OneSignal** | ✅ | ✅ | Médio | Free tier 10k |
| **SMS** | ✅ | ✅ | Alto | Pago |
**MVP Ligbox:** ntfy (Fase A) → Web Push PWA (Fase B). FCM quando existir app nativo.
---
## User stories
### US1 — Opt-in push ntfy (P1)
Como técnico, quero ativar push no app ntfy a partir de Minha conta para receber alertas sem ficar olhando o Desk.
**Aceite:**
- Toggle em Minha conta gera tópico estável
- Link + QR funcionam
- Teste push chega no celular em <30s
### US2 — Alerta ticket Wazuh (P1)
Como NOC, quero push quando ticket Wazuh crítico for criado.
**Aceite:**
- Evento webhook Wazuh push para roles `noc`, `ops_lead`, `super_admin` com opt-in
- Título/body pt-BR · link abre ticket no Desk
### US3 — Web Push browser (P2)
Como ops lead, quero notificação no browser (PWA) sem instalar ntfy.
**Aceite:**
- Permissão browser · subscription salva
- Push recebido com Desk aberto ou em background (SW)
- Click na notificação abre ticket
### US4 — Preferências por tipo (P3 — futuro)
Como usuário, quero escolher quais eventos geram push (tickets / cadastro / audit).
---
## Critérios de aceite MVP (Fase A)
- [ ] Tópico ntfy por usuário autenticado (não ativação)
- [ ] UI opt-in/opt-out em Minha conta
- [ ] Push teste via API/UI
- [ ] Push automático: novo ticket Wazuh 10
- [ ] Push automático: pedido cadastro root
- [ ] Mensagens pt-BR
- [ ] Documentação quickstart
---
## Fora de escopo (007)
- App nativo iOS/Android (Spec futura)
- FCM / APNs direto
- Push para clientes finais (portal onboard)
- SMS como canal push
- ntfy self-hosted (avaliar depois; hoje `ntfy.sh`)
---
## Riscos e mitigação
| Risco | Mitigação |
|-------|-----------|
| ntfy.sh indisponível | Log falha; e-mail continua; Fase B Web Push |
| iOS sem PWA instalado | Instruir instalar ntfy ou «Adicionar à tela inicial» |
| Spam de push | Rate limit por usuário; prioridades |
| Tópico ntfy adivinhável | Hash username + secret server-side |
---
## Referências
- Spec 004 ntfy OTP (`api/app/ntfy_notify.py`)
- Pesquisa Kimi Code Web Push, FCM, arquitetura push (2026-06-10)
- [Web Push API (MDN)](https://developer.mozilla.org/en-US/docs/Web/API/Push_API)
- [ntfy.sh docs](https://docs.ntfy.sh/)
- `specs/007-mobile-push-notifications/tasks.md`
- `specs/007-mobile-push-notifications/quickstart.md`
---
## Fases de entrega
| Fase | Entrega | Versão API |
|------|---------|------------|
| **A** | ntfy por usuário + eventos Wazuh/cadastro | 0.9.0-push-ntfy |
| **B** | Web Push PWA + manifest + SW | 0.9.1-push-pwa |
| **C** | Preferências + FCM (se app nativo) | 0.10+ |