8.8 KiB
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
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
- Usuário logado abre Minha conta → ativa push ntfy
- API gera/recupera
ntfy_topicestável:ligbox-desk-{hash(username)} - UI exibe link
https://ntfy.sh/{topic}+ QR para app ntfy - Backend grava
push_ntfy_enabled = 1emdesk_users - Em evento (ex.: ticket Wazuh), worker/API faz
POST ntfy.sh/{topic}
Fluxo Fase B — Web Push PWA
- Usuário aceita permissão de notificação no browser
- Service Worker registra
PushSubscription(endpoint + keys) - Frontend envia subscription para
POST /api/v1/push/subscribe - Backend persiste em
push_subscriptions - 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)
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):
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.htmlboot
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_admincom 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)
- ntfy.sh docs
specs/007-mobile-push-notifications/tasks.mdspecs/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+ |