Files
DashDescomplicar/docs/SPEC-dashboard-expansion-q2-2026.md
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

474 lines
15 KiB
Markdown

---
title: SPEC — Expansão DashDescomplicar Q2 2026
date: 2026-04-06
type: spec
status: active
desk_project: 65
tags: [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:**
```typescript
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:**
```typescript
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:**
```typescript
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:**
```typescript
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:**
```typescript
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
```typescript
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
```typescript
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
```env
# 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)