# Feature Specification: Ligbox Ops Console — Operação Activa (019) **Feature Branch:** `019-ops-console-active-operations` **Criado:** 2026-06-16 **Solicitado por:** Roger **Status:** 📋 Planeamento **Prioridade:** P1 **Sistema:** VM123 (UI Docker) + VM122 (API/motor) + VM104 (Wazuh) + VM112 (wizard/webhooks) **Substitui/evolui:** UI MVP `desk.ligbox.com.br` na VM122 (vanilla JS) **Depende de:** 001, 002, 004 (parcial), 009 (parcial), 010 (parcial), 018 --- ## Resumo executivo Transformar o Ligbox Ops de **painel de auditoria passiva** em **plataforma de operação activa**: ver, assumir, corrigir e acompanhar processos de **onboard**, **suporte** e **cybersecurity** num **chamado único**. A nova interface (**Ligbox Ops Console**) replica a **navegabilidade de investigação do Wazuh** (Discover, drill-down entre entidades, timeline correlacionada, severidade, tenants/agentes) num produto **próprio Ligbox** — **sem fork** do OpenSearch Dashboards. O **`CH-*` é o hub** onde toda investigação converge: timeline, observables, Assist, runbooks e fecho. Overview e Discover são portas de entrada; Wazuh nativo (VM104) permanece para análise SIEM profunda via deep link. | Decisão Roger (2026-06-16) | Valor | |----------------------------|-------| | Modelo de trabalho | **Chamado único** (`CH-*`) | | **Hub de investigação** | **`CH-*` = centro da investigação** (Opção A — Roger confirmado) | | Navegação UI | **Padrão Wazuh** (Discover, drill-down, timeline) — **não só cores** | | Aprovação de acções | **Humana** + **agentic** (políticas R0–R3) | | Monitorização frontend | **Opção A** — passo actual do wizard + eventos (sem replay de browser) | | UI | Console própria inspirada na **navegabilidade** Wazuh; Wazuh VM104 para SIEM profundo | | Host UI | **VM123** — **obrigatoriamente Docker** | --- ## Problema | Hoje (VM122 Desk MVP) | Necessidade | |----------------------|-------------| | Tickets e eventos separados por origem | **Chamado único** que agrega onboard + Wazuh + suporte | | UI simples (vanilla JS) | Console com **navegação investigativa** tipo Wazuh | | Sem hub de caso | **`CH-*` = hub** — timeline, observables, acções, fecho | | Só visualizar / fechar ticket | **Assumir**, **corrigir** (runbooks), **acompanhar** evolução | | Wazuh → alerta passivo | Alerta entra no chamado com acções de remediação | | Sem visão do wizard em tempo real | Painel **Assist**: passo actual + último erro (Opção A) | | API e UI no mesmo host | **VM123** dedicada à UI em container; **VM122** mantém motor | --- ## Arquitectura ```text Internet / LAN técnico │ ▼ CT114 Traefik ──► console.ligbox.com.br ──► VM123:ligbox-ops-console (Docker) │ │ │ │ REST + WSS ▼ ▼ api.ops.ligbox.com.br ──────────────────────► VM122 Ligbox Ops API │ │ ├─ webhooks ◄── VM112 wizard (onboard, KIMI OB-*) ├─ webhooks ◄── VM104 Wazuh (ligbox-ops.py) ├─ poll/read ◄── VM112 infra status, audit workers └─ runbooks ──► VM112 / CT114 / pfSense API (LAN, aprovado) VM104 Wazuh Manager — detecção SIEM (inalterado como motor; link «Ver no Wazuh» na Console) ``` ### Separação de responsabilidades | Componente | VM | Deploy | Função | |------------|-----|--------|--------| | **Ligbox Ops Console** | **123** | **Docker Compose** | UI React, tema Wazuh-like, WebSocket cliente | | **Ligbox Ops API** | 122 | Docker Compose (existente) | Chamados, event bus, runbooks, agentic gateway, RBAC | | **Wazuh Manager** | 104 | Docker (existente) | Detecção; ingress via webhook Spec 002 | | **Wizard / Onboard** | 112 | systemd (existente) | Emissão eventos + endpoint passo actual (Assist) | ### VM123 — restrição Docker (obrigatória) A VM123 **já executa outros serviços**. A Console **não** pode ser instalada no host (sem `npm`/`node` global, sem nginx host dedicado que conflite com portas existentes). **Regras de deploy VM123:** 1. Stack isolado em `/opt/ligbox-ops-console/` com `docker-compose.yml` próprio. 2. **Não alterar** serviços já em execução na VM123 (portas, systemd, containers existentes). 3. UI servida por container (`nginx:alpine` ou `caddy`) na porta interna **8100** (ou outra livre — validar `ss -tlnp` antes do deploy). 4. Exposição pública **apenas** via Traefik CT114 (label `Host(console.ligbox.com.br)`); bind container em `127.0.0.1:8100` ou IP LAN `10.10.10.123:8100` conforme rede Docker. 5. Variáveis via `.env` — `VITE_API_URL=https://api.ops.ligbox.com.br`, `VITE_WS_URL=wss://api.ops.ligbox.com.br`. 6. Healthcheck Docker + restart `unless-stopped`. 7. Logs: `json-file` com rotação; sem volumes partilhados com outros stacks salvo rede Traefik externa. **Compose mínimo (referência):** ```yaml # /opt/ligbox-ops-console/docker-compose.yml services: console-ui: image: ligbox/ops-console:${CONSOLE_TAG:-latest} build: ./frontend restart: unless-stopped ports: - "127.0.0.1:8100:80" environment: - API_UPSTREAM=https://api.ops.ligbox.com.br healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:80/health"] interval: 30s timeout: 5s retries: 3 ``` > **Inventário VM123:** confirmar hostname, IP LAN (`10.10.10.123` previsto) e portas ocupadas no Proxmox antes do primeiro deploy. Documentar em `docs/network/INTERFACES_PROXMOX.md` após validação. --- ## Navegação e investigação — `CH-*` como hub **Decisão Roger (confirmada):** o chamado `CH-*` é o **hub central de investigação** — não uma etiqueta no fim do fluxo. Documentação detalhada: [design/navigation-ia.md](./design/navigation-ia.md) ### Modelo mental ```text Overview / Discover ──(entrada)──► CH-* HUB ──(drill-down)──► Tenant / Wazuh / Infra │ timeline · observables · assist · runbooks · aprovações · fecho ``` | Módulo | Papel | Inspiração Wazuh | |--------|-------|------------------| | **Overview** | KPIs, funil, alertas recentes → leva ao hub | Threat Hunting overview | | **Discover** | Busca/filtros em todos os eventos → abre ou anexa ao hub | Explore → Discover | | **`CH-*` Hub** | **Investigação completa** até resolução | Alert detail + case IR | | **Tenants** | Contexto agente/VM/domínio → volta ao hub | Agent management | | **Runbooks / Aprovações** | Acções sempre no contexto de um `CH-*` | — (extensão Ligbox) | ### Regra de ouro (drill-down) Qualquer click em `domain`, `session_id`, `agent`, `rule_id`, `CH-*` ou evento **navega com contexto** — filtra Discover, abre hub, ou abre Wazuh nativo (novo tab) — tal como no Wazuh ao saltar de alerta para agente. ### O que replicar do Wazuh (navegação, não só visual) | Capacidade Wazuh | Ligbox Console | |------------------|----------------| | Threat Hunting → filtro MITRE/severidade/agente | Discover com filtros equivalentes + fontes Ligbox | | Timeline antes/depois do alerta | Timeline unificada no hub (`chamado_eventos`) | | Click agente → dashboard do host | Click tenant/domínio → scorecard + CH relacionados | | Discover full-text + time range | `GET /discover?q=&from=&to=` | | Saved searches | Pesquisas guardadas por utilizador (P2) | | Arquivo profundo | **«Investigar no Wazuh»** → VM104 (não duplicar OpenSearch) | --- ## UI — tema SOC + navegação (sem fork do motor Wazuh) ### Paleta e componentes visuais Ver [design/tokens.css](./design/tokens.css). - Fundo `#1a1f2e` / painéis `#252b3b` (referência Wazuh 4.x) - Severidade: L7–9 médio, L10–11 alto, L12+ crítico - Sidebar: Overview · Discover · Chamados · Tenants · Runbooks · Aprovações - Badges origem: `wazuh` · `onboard` · `support` · `audit` ### Layout hub `CH-*` (MVP) - **Centro:** timeline cronológica (todos os eventos + acções + notas) - **Direita (tabs):** Assist · Observables · Infra · Acções - **Rodapé:** Assumir · Executar runbook · Investigar no Wazuh · Fechar ### Observables (entidades ligadas ao hub) | Tipo | Exemplo | Acção click | |------|---------|-------------| | `domain` | `myvexx.com` | Filtra Discover ou abre scorecard | | `session_id` | `sess_abc` | Painel Assist | | `agent` | `vm112-mail` | Tenant + link Wazuh | | `rule_id` | `5712` | Discover `rule_id:5712` | | `ip` | `10.10.10.112` | Discover + observable | | `email` | `admin@dominio` | Contexto onboard | Persistência: tabela `chamado_observables` (ver plan.md). ### O que a Console acrescenta (Wazuh nativo não tem) - Hub `CH-*` com ciclo de vida e runbooks - Painel **Assist** (Opção A) - Fila **Aprovações** humano + agentic - Scorecard infra embutido no hub - Deep link «Investigar no Wazuh» (SIEM profundo) --- ## Modelo de dados — Chamado único (`CH-*`) ### Identificador - Formato: `CH-YYYY-NNNNN` (ex.: `CH-2026-00042`) - Substitui visualmente «Ticket #id» no MVP; API mantém `tickets.id` interno + `public_id` ### Agregação Um chamado agrupa eventos quando coincidem (por ordem de prioridade): 1. `session_id` + `domain` (onboard) 2. `domain` + janela 72h (sem session_id) 3. `wazuh.agent.id` + `domain` / IP tenant 4. Manual: ops funde chamados (acção R2) ### Estados ```text novo → assumido → em_diagnostico → em_correcao → aguardando_cliente → resolvido → fechado ↑ │ └──── reaberto ──────┘ ``` ### Campos principais (`chamados`) | Campo | Tipo | Descrição | |-------|------|-----------| | `public_id` | string | `CH-2026-00042` | | `status` | enum | Estados acima | | `assignee` | user_id | Técnico que assumiu | | `domain` | string | Domínio principal | | `session_id` | string | Wizard session | | `wizard_step` | string | Passo actual (Opção A, poll/WSS) | | `wizard_step_at` | datetime | Última actualização passo | | `sources` | json[] | `wazuh`, `onboard`, `support`, `audit` | | `max_severity` | int | Maior level Wazuh associado | | `created_at` / `updated_at` | datetime | Auditoria | Eventos existentes em `webhook_events` ganham `chamado_id` FK. ### Hub — secções da API/UI | Secção | Dados | |--------|-------| | `timeline` | Eventos + execuções runbook + notas + aprovações | | `observables` | Entidades extraídas automaticamente dos payloads | | `assist` | Passo wizard Opção A | | `infra` | Último scorecard domínio (proxy 009) | | `acoes_pendentes` | Runbooks e aprovações em fila | | `links` | `wazuh_deep_link`, wizard admin, tenant | --- ## Aprovações — humano + agentic | Nível | Nome | Quem executa | Exemplos | |-------|------|--------------|----------| | **R0** | Auto | Política agentic | Re-poll infra status, refresh timeline | | **R1** | Agentic + clique | Agente propõe; humano confirma | Re-sync Traefik cert, reload nginx | | **R2** | Humano obrigatório | Técnico sénior | zmprov, purge domínio (Spec 017), pfSense NAT | | **R3** | Dupla aprovação | Lead + segundo par | Purge produção, alteração WAN | ### Fluxo agentic ```text Evento → Agente A6/A7 analisa → Proposta runbook + confiança % → R0: executa + regista na timeline → R1: fila «Aprovações» na Console → humano Aprovar/Rejeitar → R2/R3: só botão manual após checklist ``` Toda execução gera registo `action_executed` na timeline com `actor` (user | agent | system). --- ## Assist onboard — Opção A ### Dados expostos (sem replay de browser) | Campo | Fonte | |-------|-------| | `wizard_step` | VM112 `GET /api/onboarding/session/{id}/status` (novo) | | `wizard_step_label` | Mapa estático frontend wizard | | `last_error` | Último `onboarding.failed` ou HTTP 4xx/5xx webhook | | `time_on_step_sec` | Calculado no VM112 | | `planned_email` | Session / portal handoff (sem senha) | ### Transporte - **Poll** 30s no painel Chamado (MVP) - **WebSocket** `wss://api.ops.ligbox.com.br/v1/chamados/{id}/live` (Fase 2) **Proibido:** gravar DOM, screenshots, ou keystrokes do cliente. --- ## User Stories ### US-1 — Chamado único (P1) **Como** ops lead, **quero** um único chamado por incidente de cliente, **para** não perseguir ticket Wazuh + OB-* + infra em filas separadas. **Aceite:** 1. `wazuh.alert` L12 + `onboarding.failed` mesmo domínio → mesmo `CH-*` 2. Timeline mostra ambos ordenados por timestamp 3. Assumir chamado bloqueia auto-fecho até resolução --- ### US-2 — Console UI estilo Wazuh na VM123 Docker (P1) **Como** técnico NOC, **quero** a Console em Docker na VM123, **para** não conflitar com serviços já instalados nessa VM. **Aceite:** 1. `docker compose up -d` sobe UI sem reiniciar outros containers host 2. `https://console.ligbox.com.br` serve a SPA 3. Tema escuro e Discover reconhecível como «estilo Wazuh» 4. Healthcheck verde no `docker ps` --- ### US-3 — Assumir e corrigir (P1) **Como** técnico, **quero** assumir um chamado e executar runbooks aprovados, **para** resolver sem SSH manual. **Aceite:** 1. Botão **Assumir** define `assignee` e estado `assumido` 2. Runbook R1 aparece em «Aprovações» com diff da acção proposta 3. Após execução, check infra re-corre e timeline actualiza --- ### US-4 — Assist passo wizard (P1) **Como** suporte, **quero** ver em que passo o cliente está no onboard, **para** assistir sem pedir screenshots. **Aceite:** 1. Painel lateral mostra passo actual ≤ 30s de atraso (poll MVP) 2. Não exibe senhas nem conteúdo de campos privados 3. Link «Abrir wizard» (read-only admin) para ops com role `ops_lead` --- ### US-5 — Aprovação agentic (P2) **Como** ops lead, **quero** que o agente proponha correcções R0/R1, **para** reduzir tempo de diagnóstico. **Aceite:** 1. Proposta visível com confiança % e comandos resumidos (não secrets) 2. R0 executado automaticamente com linha na timeline `actor=agent` 3. R2 nunca executa sem clique humano explícito --- ### US-6 — Discover unificado (P1) **Como** analista SOC, **quero** filtrar todos os eventos num ecrã Discover, **para** investigar como no Wazuh mas com contexto Ligbox. **Aceite:** 1. Filtros: origem, domínio, severidade, `session_id`, intervalo temporal 2. Click em evento **abre hub `CH-*` existente ou cria novo** em ≤ 2 cliques 3. Eventos Wazuh mostram `rule.id`, `agent.name`, level --- ### US-7 — Hub `CH-*` investigação (P1) **Como** técnico ops, **quero** que o chamado seja o centro de toda investigação, **para** ver timeline, observables, Assist e acções no mesmo ecrã até fechar. **Aceite:** 1. Rota `/chamados/CH-*` mostra timeline + tabs Assist/Observables/Infra/Acções 2. Click em observable navega com contexto (Discover filtrado ou tenant) 3. Botão «Investigar no Wazuh» abre VM104 com agente + janela temporal 4. Runbooks executados só dentro do hub; resultado aparece na timeline 5. URL partilhável entre técnicos da equipa --- ## API VM122 — endpoints novos / alterados | Método | Path | Descrição | |--------|------|-----------| | GET | `/api/v1/chamados` | Lista com filtros (estado, domínio, assignee) | | GET | `/api/v1/chamados/{public_id}` | **Hub** — timeline + observables + assist + infra + acções | | POST | `/api/v1/chamados/{public_id}/eventos/anexar` | Anexar eventos Discover ao hub | | POST | `/api/v1/chamados/{public_id}/notas` | Nota investigação na timeline | | POST | `/api/v1/chamados/{public_id}/assumir` | Assume chamado | | PATCH | `/api/v1/chamados/{public_id}` | Estado, assignee, notas | | POST | `/api/v1/chamados/{public_id}/runbooks/{code}/executar` | Enfileira execução | | GET | `/api/v1/aprovacoes` | Fila R1/R3 | | POST | `/api/v1/aprovacoes/{id}/aprovar` | Humano aprova proposta agentic | | GET | `/api/v1/discover` | Feed paginado (eventos + metadados) | | WS | `/api/v1/chamados/{public_id}/live` | Passo wizard + novos eventos (Fase 2) | **VM112 (novo):** | Método | Path | Descrição | |--------|------|-----------| | GET | `/api/onboarding/session/{session_id}/ops-status` | Passo actual Opção A (LAN + secret) | --- ## Runbooks MVP (Fase 1) | Código | Nível | Descrição | |--------|-------|-----------| | `infra_recheck` | R0 | Re-correr checks infra domínio | | `traefik_cert_sync` | R1 | Sync cert CT114 (Spec 011) | | `admin_nginx_reload` | R1 | Reload carbonio-nginx admin block | | `webmail_gate_check` | R0 | Verificar redirect webmail gate | | `zmproxy_admin_provision` | R2 | Provision admin vhost (Spec 010) | | `domain_purge` | R3 | Purge completo Spec 017 | | `wazuh_acknowledge` | R1 | Marcar alerta tratado + nota | | `escalate_kimi_human` | R0 | Liga OB-* ao chamado único | --- ## Fases de entrega | Fase | Entrega | VM | Semanas | |------|---------|-----|---------| | **F1** | Spec + design tokens + wireframes | — | 1 | | **F2** | API chamado único + migração tickets | 122 | 2–3 | | **F3** | Console Docker MVP (Overview, Discover, Chamados) | **123** | 3–4 | | **F4** | Runbooks R0–R2 + fila aprovações | 122 + 123 | 3–4 | | **F5** | Assist Opção A (poll passo wizard) | 112 + 122 + 123 | 2–3 | | **F6** | Agentic R0/R1 + WebSocket live | 122 + 123 | 3–4 | **MVP (F1–F4):** ~10–12 semanas **Completo (F1–F6):** ~16–20 semanas --- ## Segurança e rede - Console e API: autenticação JWT Spec 003 (RBAC) - VM112 `ops-status`: header `X-Ops-Secret`, LAN-only `10.10.10.122` - VM123: fail2ban no host (já esperado); container sem privilégios (`no-new-privileges`) - CORS: `console.ligbox.com.br` → `api.ops.ligbox.com.br` apenas - Runbooks R2/R3: audit log imutável em SQLite + export diário --- ## Out of scope (esta spec) - Fork do código `wazuh-dashboard` / OpenSearch Dashboards - Replay de sessão browser / gravação DOM - Substituir Wazuh manager na VM104 - Postgres cluster (MVP mantém SQLite VM122) - Expor API ops à internet pública sem VPN/pfSense --- ## Critérios de aceite globais - [ ] Console acessível em `https://console.ligbox.com.br` via Docker VM123 - [ ] Deploy Console não reinicia nem altera containers pré-existentes na VM123 - [ ] Chamado único agrega Wazuh + onboard + suporte no mesmo `CH-*` - [ ] **Hub `CH-*`:** timeline + observables + Assist + runbooks no mesmo ecrã - [ ] Discover → hub em ≤ 2 cliques; drill-down em observables funcional - [ ] UI com navegação investigativa tipo Wazuh (não só tema escuro) - [ ] Assumir + timeline + runbook R1 com aprovação humana funcionais - [ ] Assist mostra passo wizard sem dados sensíveis (Opção A) - [ ] `desk.ligbox.com.br` redirecciona para Console ou deprecado com aviso 90 dias --- ## Referências | Documento | Path | |-----------|------| | Wazuh ingress | `specs/002-wazuh-integration/spec.md` | | Funil onboarding | `specs/004-onboard-funnel-events/spec.md` | | Audit scorecard | `specs/009-ops-audit-overview/spec.md` | | Admin validation | `specs/010-admin-domain-validation/spec.md` | | Serviços MOSP | `specs/018-service-orchestration/spec.md` | | Visão plataforma | `docs/architecture/VISAO_PLATAFORMA_LIGBOX_OPS.md` | | Constitution | `.specify/memory/constitution.md` | --- ## Histórico | Data | Autor | Alteração | |------|-------|-----------| | 2026-06-16 | Roger + Cursor | Spec inicial — chamado único, UI Wazuh-like, VM123 Docker | | 2026-06-16 | Roger | **Hub `CH-*` = investigação** (Opção A); navegação Wazuh, não só design |