Files
DashDescomplicar/docs/SPEC-dashboard-expansion-q2-2026.md
T
ealmeida 12f688ff7c feat: adicionar 5 novos painéis ao dashboard (MCPs, n8n, Paperclip, IA, Operações)
Expansão do dashboard de 3 para 8 páginas com dados reais do stack:
- MCPs: monitorização de 33 MCPs no gateway com ping e estado online/offline
- n8n: 14 workflows com último run, duração e falhas 24h
- Paperclip: 16 agentes operacionais, routines e issues (PostgreSQL)
- IA/Claude: visão das 3 camadas (189 skills, 72 agents, 39 MCPs, CARL)
- Operações: tickets Desk CRM por departamento + cobertura PROCs

16 ficheiros novos (3042 linhas), 3 existentes editados.
Nova dependência: pg (PostgreSQL client para Paperclip).
Audit: 0 vulnerabilidades (npm audit fix aplicado).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 20:58:48 +01:00

15 KiB

title, date, type, status, desk_project, tags
title date type status desk_project tags
SPEC — Expansão DashDescomplicar Q2 2026 2026-04-06 spec active 65
dashboard
expansion
mcps
paperclip
n8n
claude-code

SPEC — Expansão DashDescomplicar Q2 2026

1. Contexto

O DashDescomplicar é o painel de gestão interno da Descomplicar®. Stack: React 19 + Vite + Tailwind CSS 4 + Express 4 + MySQL (Desk CRM BD). Deploy em EasyPanel via Dockerfile.

Estado actual (3 páginas)

Página Rotas API Dados
Dashboard (App.tsx) /api/dashboard Tarefas (urgente/alta/vencidas/em teste), leads (contactar/followup/proposta), projectos, billing 360, calendário Google, timesheet
Monitor /api/monitor, /api/hetzner, /api/server-metrics, /api/wp-monitor, /api/diagnostic Servidores Hetzner (CPU/rede/disco), serviços HTTP (11 URLs), EasyPanel containers, sites WordPress (CWP)
Financeiro /api/financial Vendas/despesas mês e ano, lucro, categorias, evolução mensal 12 meses

O que falta (referência: plano-migracao-mcps-gateway-auth.md, Fase 5)

Novos painéis para reflectir o stack completo: MCPs (33 no gateway), n8n (14 workflows), Paperclip (16 agentes operacionais), Claude Code/IA (189 skills, 72 agents, 9 hooks), LightRAG (knowledge graph), Desk CRM expandido (tickets, SLAs), e Operações (worklogs, PROCs, calendário).

Auth

OIDC com Authentik já implementado no frontend (react-oidc-context, AuthWrapper.tsx, config.ts). Backend tem placeholder (OIDC_ENABLED=true). Falta activar em produção.


2. Objectivos

  1. Expandir o dashboard de 3 para 8 páginas
  2. Cada novo painel usa dados reais via API (gateway MCPs, BD MySQL, APIs HTTP)
  3. Manter a consistência visual (dark theme, Tailwind, framer-motion, lucide-react)
  4. Zero dependências novas — usar as existentes (recharts, framer-motion, lucide)
  5. Cada painel é independente — pode ser implementado e testado isoladamente

3. Arquitectura de dados (fontes por painel)

Express API (porta 3001)
├── /api/dashboard     → MySQL (Desk CRM) + Google Calendar API    [EXISTE]
├── /api/monitor       → MySQL (tbl_eal_monitoring) + Hetzner API  [EXISTE]
├── /api/financial     → MySQL (Desk CRM invoices/expenses)        [EXISTE]
├── /api/mcps          → HTTP GET gateway.descomplicar.pt/health + per-MCP ping  [NOVO]
├── /api/n8n           → HTTP GET automator.descomplicar.pt/api/v1 (API key)     [NOVO]
├── /api/paperclip     → PostgreSQL clip.descomplicar.pt (porta 54329)           [NOVO]
├── /api/ai            → Ficheiros locais + MySQL (stats)                        [NOVO]
└── /api/operations    → MySQL (Desk CRM) + Google Calendar                      [NOVO]

4. Especificação por painel

4.1 Painel MCPs (nova página /mcps)

Objectivo: Ver todos os 33+2 MCPs com estado online/offline em tempo real.

Rota API: GET /api/mcps

Fonte de dados:

  • Gateway health: GET https://gateway.descomplicar.pt/health (sem auth, já existe)
  • Per-MCP ping: GET https://gateway.descomplicar.pt/v1/<nome>/mcp com Bearer token (resposta 200 = online)
  • Lista estática dos MCPs com metadados (nome, porta, categoria, enabled/disabled)

Dados retornados:

interface McpStatus {
  name: string           // "desk-crm-v3"
  port: number           // 3150
  category: string       // "crm" | "infra" | "ai" | "tools" | "external"
  enabled: boolean       // true/false em claude.json
  status: 'online' | 'offline' | 'disabled' | 'unknown'
  response_time_ms: number | null
  last_check: string     // ISO timestamp
  tools_count?: number   // número de tools (se conhecido)
}

interface McpDashboard {
  gateway_status: 'online' | 'offline'
  total: number
  online: number
  offline: number
  disabled: number
  mcps: McpStatus[]
  auth: {
    method: string       // "dual-layer: IP whitelist + Bearer token"
    token_expires: string | null
  }
}

UI (página McpMonitor.tsx):

  • Header com stats gerais (total/online/offline/disabled)
  • Grid de cards por MCP, agrupados por categoria
  • Indicador de cor: verde (online), vermelho (offline), cinza (disabled)
  • Response time badge em cada card
  • Filtros: por categoria, por estado
  • Botão refresh manual

Implementação backend (api/services/mcps.ts):

  • Lista hardcoded de MCPs com metadados (extraída de port-map.json e claude.json)
  • Ping paralelo a cada MCP enabled (Promise.allSettled com timeout 5s)
  • Cache de 60 segundos (evitar spam ao gateway)

4.2 Painel n8n (nova página /n8n)

Objectivo: Ver 14 workflows operacionais com estado, último run, próximo run.

Rota API: GET /api/n8n

Fonte de dados:

  • n8n API REST: https://automator.descomplicar.pt/api/v1/workflows (API key em env)
  • n8n API REST: https://automator.descomplicar.pt/api/v1/executions?limit=50

Dados retornados:

interface N8nWorkflow {
  id: string
  name: string
  active: boolean
  last_execution: {
    status: 'success' | 'error' | 'running' | null
    started_at: string | null
    finished_at: string | null
    duration_ms: number | null
  } | null
  tags: string[]
}

interface N8nDashboard {
  total: number
  active: number
  inactive: number
  failed_24h: number
  workflows: N8nWorkflow[]
  last_updated: string
}

UI (página N8nMonitor.tsx):

  • Stats cards: total/activos/falhas 24h
  • Tabela de workflows: nome, activo, último run (com cor: verde/vermelho), duração
  • Filtro: activos/todos
  • Alerta visual se algum workflow falhou nas últimas 24h

Env vars necessárias:

  • N8N_API_URL (default: https://automator.descomplicar.pt/api/v1)
  • N8N_API_KEY

4.3 Painel Paperclip (nova página /paperclip)

Objectivo: Ver os 16 agentes operacionais, routines, e issues.

Rota API: GET /api/paperclip

Fonte de dados:

  • PostgreSQL do Paperclip: clip.descomplicar.pt:54329 (credenciais em env)
  • Tabelas: agents, agent_runs, routines, routine_executions, issues

Dados retornados:

interface PaperclipAgent {
  id: string
  name: string
  role: string           // "CEO", "CTO", "Director", "Specialist"
  status: 'active' | 'idle' | 'error' | 'archived'
  last_heartbeat: string | null
  last_run: string | null
  total_runs: number
}

interface PaperclipRoutine {
  id: string
  name: string
  cron: string
  active: boolean
  last_run: string | null
  last_status: 'success' | 'error' | null
  next_run: string | null
}

interface PaperclipDashboard {
  agents: {
    total: number
    active: number
    idle: number
    error: number
    list: PaperclipAgent[]
  }
  routines: {
    total: number
    active: number
    list: PaperclipRoutine[]
  }
  issues: {
    open: number
    in_progress: number
    closed_7d: number
  }
}

UI (página Paperclip.tsx):

  • Stats cards: agentes activos/idle/error, routines activas
  • Grid de cards para agentes (agrupados por role/nível hierárquico)
  • Tabela de routines com cron, último/próximo run
  • Contador de issues (open/in-progress/closed)

Env vars necessárias:

  • PAPERCLIP_DB_HOST (default: clip.descomplicar.pt)
  • PAPERCLIP_DB_PORT (default: 54329)
  • PAPERCLIP_DB_NAME
  • PAPERCLIP_DB_USER
  • PAPERCLIP_DB_PASS

Dependência adicional: pg (PostgreSQL client para Node.js) — única nova dependência no projecto


4.4 Painel Claude Code / IA (nova página /ai)

Objectivo: Ver skills top, agents, MCPs activos, e CARL.

Rota API: GET /api/ai

Fonte de dados:

  • Contagens estáticas derivadas do STK-Estado-Actual.md (actualizar periodicamente)
  • CARL config: leitura de /media/ealmeida/Dados/.carl/carl.json (se acessível via EasyPanel volume mount, senão estático)
  • Hooks: contagem de ficheiros em ~/.claude/hooks/

Dados retornados:

interface AiDashboard {
  skills: {
    total: number        // 189
    directas: number     // 31
    plugins: number      // 158
    top_10: string[]     // nomes das 10 mais usadas
  }
  agents: {
    total: number        // 72
    directos: number     // 18
    plugins: number      // 54
  }
  mcps: {
    total: number        // 39
    enabled: number      // 10
    gateway: number      // 33
    local: number        // 2
  }
  hooks: {
    total_files: number  // 26
    active: number       // 9
  }
  carl: {
    domains: number      // 7
    rules: number        // ~45
    decisions: number
  }
  plugins: {
    total: number        // 14 descomplicar + 6 oficiais + 3 terceiros
    active: number       // 6
  }
}

UI (página AiOverview.tsx):

  • Cards grandes com métricas (skills, agents, MCPs, hooks, plugins)
  • Secção CARL: domínios com contagem de regras
  • Sem interactividade complexa — é um painel informativo/snapshot

Nota: Este painel é maioritariamente estático. Os dados mudam raramente (quando se adicionam skills/agents). Actualização via endpoint manual ou ficheiro JSON servido estáticamente.


4.5 Painel Operações (nova página /operations)

Objectivo: Visão operacional — tickets, SLAs, procedimentos.

Rota API: GET /api/operations

Fonte de dados:

  • MySQL (Desk CRM): tickets abertos, por prioridade, SLAs
  • Contagens estáticas: PROCs (48), departamentos (7)

Dados retornados:

interface OperationsDashboard {
  tickets: {
    open: number
    high_priority: number
    avg_response_hours: number
    by_department: { dept: string; count: number }[]
  }
  procedures: {
    total: number        // 48
    departments: number  // 7 (D1-D7)
    coverage: { dept: string; procs: number; pct: number }[]
  }
}

UI (página Operations.tsx):

  • Cards: tickets abertos, alta prioridade, tempo médio resposta
  • Gráfico barras: tickets por departamento
  • Tabela cobertura PROCs por departamento

5. Alterações ao código existente

5.1 Layout.tsx — adicionar itens de navegação

const NAV_ITEMS: NavItem[] = [
  { to: '/', label: 'Dashboard', icon: LayoutDashboard },
  { to: '/monitor', label: 'Monitor', icon: Activity },
  { to: '/financial', label: 'Financeiro', icon: CreditCard },
  // NOVOS:
  { to: '/mcps', label: 'MCPs', icon: Network },
  { to: '/n8n', label: 'Automações', icon: Workflow },
  { to: '/paperclip', label: 'Paperclip', icon: Bot },
  { to: '/ai', label: 'IA / Claude', icon: Brain },
  { to: '/operations', label: 'Operações', icon: ClipboardList },
]

5.2 App.tsx — adicionar rotas

Novas rotas no React Router para cada página.

5.3 server.ts — registar novas rotas API

import mcpsRouter from './routes/mcps.js'
import n8nRouter from './routes/n8n.js'
import paperclipRouter from './routes/paperclip.js'
import aiRouter from './routes/ai.js'
import operationsRouter from './routes/operations.js'

app.use('/api/mcps', mcpsRouter)
app.use('/api/n8n', n8nRouter)
app.use('/api/paperclip', paperclipRouter)
app.use('/api/ai', aiRouter)
app.use('/api/operations', operationsRouter)

6. Ficheiros a criar (por sprint)

Sprint 1 — MCPs + n8n (estimativa: 8-10h)

api/routes/mcps.ts          # Rota GET /api/mcps
api/services/mcps.ts        # Ping gateway, lista MCPs, cache
api/routes/n8n.ts           # Rota GET /api/n8n
api/services/n8n.ts         # Chamadas API n8n
src/pages/McpMonitor.tsx    # Página frontend MCPs
src/pages/N8nMonitor.tsx    # Página frontend n8n

Sprint 2 — Paperclip (estimativa: 6-8h)

api/services/paperclip-db.ts  # Conexão PostgreSQL Paperclip
api/routes/paperclip.ts       # Rota GET /api/paperclip
api/services/paperclip.ts     # Queries aos agentes/routines/issues
src/pages/Paperclip.tsx       # Página frontend Paperclip

Sprint 3 — IA + Operações (estimativa: 4-6h)

api/routes/ai.ts            # Rota GET /api/ai
api/services/ai.ts          # Dados estáticos/contagens IA
api/routes/operations.ts    # Rota GET /api/operations
api/services/operations.ts  # Queries tickets + PROCs
src/pages/AiOverview.tsx    # Página frontend IA
src/pages/Operations.tsx    # Página frontend Operações

Sprint 4 — Integração + polish (estimativa: 2-3h)

# Alterações a ficheiros existentes:
src/components/Layout.tsx   # Adicionar 5 itens nav
src/App.tsx                 # Adicionar 5 rotas (no routing section)
api/server.ts               # Registar 5 routers novos
.env.example                # Novas env vars documentadas
README.md                   # Actualizar documentação

7. Env vars novas necessárias

# MCPs Gateway
MCP_GATEWAY_URL=https://gateway.descomplicar.pt
MCP_GATEWAY_TOKEN=<authentik-bearer-token>

# n8n
N8N_API_URL=https://automator.descomplicar.pt/api/v1
N8N_API_KEY=<n8n-api-key>

# Paperclip PostgreSQL
PAPERCLIP_DB_HOST=clip.descomplicar.pt
PAPERCLIP_DB_PORT=54329
PAPERCLIP_DB_NAME=paperclip
PAPERCLIP_DB_USER=<user>
PAPERCLIP_DB_PASS=<pass>

8. Dependências

Pacote Razão Sprint
pg PostgreSQL client (Paperclip BD) Sprint 2

Todas as outras dependências já existem no projecto (recharts, framer-motion, lucide-react, express, mysql2, zod).


9. Padrões a seguir (consistência)

  • Backend: Router Express separado por domínio. Service file com queries. Async/await com try/catch.
  • Frontend: Página como componente único com useState/useEffect/useCallback. motion.div com containerVariants/itemVariants. Cards com gradientes e lucide icons.
  • Estilo: Dark theme (bg-zinc-950, borders white/10, text zinc-400/white). Gradientes brand-500/violet-600. Rounded-2xl nos cards.
  • Error handling: try/catch no backend → 500 JSON. Frontend → estado de loading/error com retry.
  • Cache: Backend cache simples com timestamp (60s para MCPs, 300s para n8n).

10. Riscos e mitigações

Risco Mitigação
n8n API key expirar Documentar no .env.example, alertar na UI
Paperclip BD inacessível do EasyPanel Verificar rede Docker Swarm, fallback com dados estáticos
Gateway health check lento (33 MCPs) Promise.allSettled com timeout 5s + cache 60s
Página MCPs demasiado pesada Ping apenas MCPs enabled (10), disabled mostrados como cinza sem ping

11. Critérios de aceitação

  • Todas as 8 páginas carregam sem erros
  • Cada API retorna dados reais (não mocks)
  • Navegação sidebar mostra todas as 8 páginas
  • Mobile responsive (sidebar colapsável funciona com 8 itens)
  • Build de produção compila sem erros (npm run build)
  • Zero vulnerabilidades de segurança (npm audit)

12. Fora de escopo

  • Auth OIDC em produção (já implementado, activar separadamente)
  • LightRAG painel visual com grafo D3.js (fase futura, complexidade alta)
  • Painel Desk CRM expandido com Kanban (já tem dados no Dashboard principal)
  • Botões de acção (enable/disable MCP, restart workflow) — apenas visualização
  • Testes unitários (existem mas não são prioritários para esta expansão)