# 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+ |
