269 lines
8.8 KiB
Markdown
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 só 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+ |
|