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