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>
This commit is contained in:
2026-04-06 20:58:48 +01:00
parent a4271fd06a
commit 12f688ff7c
23 changed files with 4123 additions and 21 deletions
+396
View File
@@ -0,0 +1,396 @@
---
title: PLAN Conductor — Expansão DashDescomplicar
date: 2026-04-06
type: plan
status: active
spec: SPEC-dashboard-expansion-q2-2026.md
tags: [conductor, plan, dashboard, parallel]
---
# Plano Conductor — Expansão DashDescomplicar
**Spec:** `docs/SPEC-dashboard-expansion-q2-2026.md`
**Projecto:** `/media/ealmeida/Dados/Dev/DashDescomplicar/`
**Método:** Conductor parallel sprints — agentes independentes por domínio
---
## Estratégia de paralelização
Cada painel (backend + frontend) é **independente** — ficheiros distintos, sem dependências cruzadas. A integração (Layout, App, server.ts) é feita no final por um único agente coordenador.
```
┌─────────────┐
│ Coordenador │
│ (Sprint 4) │
└──────┬──────┘
┌──────────────┼──────────────┐
Sprint 1 │ Sprint 3
┌────┴────┐ Sprint 2 ┌────┴────┐
│ │ │ │ │
Agent A Agent B Agent C Agent D Agent E
MCPs n8n Paperclip IA Operações
```
**Agentes A-E correm em paralelo.** Agente F (coordenador) corre depois, integrando tudo.
---
## Pré-requisitos (executar antes do conductor)
1. Instalar `pg` (PostgreSQL client):
```bash
cd /media/ealmeida/Dados/Dev/DashDescomplicar && npm install pg @types/pg
```
2. Verificar env vars disponíveis no EasyPanel (MCP_GATEWAY_TOKEN, N8N_API_KEY, PAPERCLIP_DB_*)
---
## Agent A — Painel MCPs
**Tipo:** `javascript-fullstack-specialist`
**Isolation:** worktree
**Ficheiros a criar:**
- `api/services/mcps.ts`
- `api/routes/mcps.ts`
- `src/pages/McpMonitor.tsx`
**Prompt:**
```
Estás a trabalhar no projecto DashDescomplicar (/media/ealmeida/Dados/Dev/DashDescomplicar/).
Stack: React 19 + Vite + Tailwind CSS 4 + Express 4 + TypeScript.
Lê a spec completa em docs/SPEC-dashboard-expansion-q2-2026.md, secção 4.1 (Painel MCPs).
Cria 3 ficheiros:
1. api/services/mcps.ts — Service que:
- Tem lista hardcoded de 35 MCPs (nome, porta, categoria, enabled)
- Faz ping paralelo (Promise.allSettled, timeout 5s) aos MCPs enabled via HTTP GET
- Gateway URL: process.env.MCP_GATEWAY_URL || 'https://gateway.descomplicar.pt'
- Bearer token: process.env.MCP_GATEWAY_TOKEN
- Cache de 60 segundos (variável em memória com timestamp)
- Retorna McpDashboard conforme spec
2. api/routes/mcps.ts — Router Express com GET /
- Chama o service e retorna JSON
- try/catch com 500 error handling (padrão dos outros routers no projecto)
3. src/pages/McpMonitor.tsx — Página React que:
- Faz fetch a /api/mcps com useEffect
- Mostra header com stats (total/online/offline/disabled)
- Grid de cards agrupados por categoria (crm, infra, ai, tools, external)
- Card com: nome, porta, status (cor), response_time
- Botão refresh manual
- Loading state e error state
- Segue estilo visual do projecto: ler src/pages/Monitor.tsx como referência (dark theme, motion.div, lucide icons, containerVariants/itemVariants)
Lista dos MCPs para hardcoding:
- CRM: desk-crm-v3 (3150), desk-project-minimal (3153)
- Infra: ssh-unified (3192), filesystem (local), chrome-devtools (local)
- AI: lightrag (3160), notebooklm (3190), context7 (3169), replicate (3176), memory-supabase (3151)
- Tools: mcp-time (3155), deepl (3188), pexels (3175), vimeo (3177), drawio (3184)
- External: google-workspace (3156), google-analytics (3164), gsc (3165), youtube (3166), youtube-research (3167), moloni (3158), n8n (3171), gitea (3162), stitch (external), design-systems (external)
- Gateway: authentik (3191), spaceship (3189), puppeteer (3193), lighthouse (3194)
- Locais (disabled ping): filesystem, chrome-devtools
- MCPs em .mcp.json: carl-mcp (local, porta variável), reonic (3187)
Não alteres nenhum ficheiro existente. Apenas cria os 3 novos.
```
---
## Agent B — Painel n8n
**Tipo:** `javascript-fullstack-specialist`
**Isolation:** worktree
**Ficheiros a criar:**
- `api/services/n8n.ts`
- `api/routes/n8n.ts`
- `src/pages/N8nMonitor.tsx`
**Prompt:**
```
Estás a trabalhar no projecto DashDescomplicar (/media/ealmeida/Dados/Dev/DashDescomplicar/).
Stack: React 19 + Vite + Tailwind CSS 4 + Express 4 + TypeScript.
Lê a spec completa em docs/SPEC-dashboard-expansion-q2-2026.md, secção 4.2 (Painel n8n).
Cria 3 ficheiros:
1. api/services/n8n.ts — Service que:
- Chama API REST n8n: GET /workflows e GET /executions?limit=50
- URL base: process.env.N8N_API_URL || 'https://automator.descomplicar.pt/api/v1'
- Auth: header X-N8N-API-KEY com process.env.N8N_API_KEY
- Cache de 300 segundos
- Retorna N8nDashboard conforme spec (total, active, failed_24h, workflows com last_execution)
2. api/routes/n8n.ts — Router Express com GET /
- try/catch com 500 error handling
3. src/pages/N8nMonitor.tsx — Página React que:
- Faz fetch a /api/n8n
- Stats cards: total workflows, activos, falhas 24h (destaque vermelho se >0)
- Tabela com: nome, activo (badge), último run (data + status com cor), duração
- Filtro toggle: activos/todos
- Segue estilo visual: ler src/pages/Financial.tsx como referência
Não alteres nenhum ficheiro existente. Apenas cria os 3 novos.
```
---
## Agent C — Painel Paperclip
**Tipo:** `javascript-fullstack-specialist`
**Isolation:** worktree
**Ficheiros a criar:**
- `api/services/paperclip-db.ts`
- `api/services/paperclip.ts`
- `api/routes/paperclip.ts`
- `src/pages/Paperclip.tsx`
**Prompt:**
```
Estás a trabalhar no projecto DashDescomplicar (/media/ealmeida/Dados/Dev/DashDescomplicar/).
Stack: React 19 + Vite + Tailwind CSS 4 + Express 4 + TypeScript.
Lê a spec completa em docs/SPEC-dashboard-expansion-q2-2026.md, secção 4.3 (Painel Paperclip).
O pacote `pg` já foi instalado (npm install pg @types/pg).
Cria 4 ficheiros:
1. api/services/paperclip-db.ts — Pool PostgreSQL:
- Host: process.env.PAPERCLIP_DB_HOST || 'clip.descomplicar.pt'
- Port: process.env.PAPERCLIP_DB_PORT || 54329
- Database: process.env.PAPERCLIP_DB_NAME || 'paperclip'
- User/Pass: process.env.PAPERCLIP_DB_USER, process.env.PAPERCLIP_DB_PASS
- Pool com max 5 conexões
- Validação de credenciais obrigatória (throw se não definidas)
- Export default pool
2. api/services/paperclip.ts — Queries:
- getAgents(): SELECT id, name, role, status, last_heartbeat, total_runs FROM agents WHERE status != 'archived'
- getRoutines(): SELECT id, name, cron, active, last_run, last_status FROM routines
- getIssueStats(): COUNT por estado (open, in_progress, closed últimos 7 dias)
- Retorna PaperclipDashboard conforme spec
- NOTA: os nomes exactos das tabelas e colunas podem variar — usar nomes razoáveis e documentar com comentário que podem precisar de ajuste
3. api/routes/paperclip.ts — Router Express com GET /
- try/catch, se BD inacessível retornar dados fallback (zeros)
4. src/pages/Paperclip.tsx — Página React:
- Stats cards: agentes activos/idle/error, routines activas
- Grid de cards para agentes, agrupados por role (C-Level, Director, Specialist)
- Cor do card por status: active=verde, idle=amarelo, error=vermelho
- Tabela de routines: nome, cron, activa, último run, status
- Segue estilo visual do projecto
Não alteres nenhum ficheiro existente. Apenas cria os 4 novos.
```
---
## Agent D — Painel IA / Claude Code
**Tipo:** `javascript-fullstack-specialist`
**Isolation:** worktree
**Ficheiros a criar:**
- `api/services/ai.ts`
- `api/routes/ai.ts`
- `src/pages/AiOverview.tsx`
**Prompt:**
```
Estás a trabalhar no projecto DashDescomplicar (/media/ealmeida/Dados/Dev/DashDescomplicar/).
Stack: React 19 + Vite + Tailwind CSS 4 + Express 4 + TypeScript.
Lê a spec completa em docs/SPEC-dashboard-expansion-q2-2026.md, secção 4.4 (Painel Claude Code / IA).
Cria 3 ficheiros:
1. api/services/ai.ts — Service que:
- Retorna dados maioritariamente estáticos (actualizados manualmente)
- Dados reais do stack (fonte: STK-Estado-Actual.md de 04-04-2026):
- Skills: 189 total (31 directas + 158 plugins)
- Agents CC: 72 (18 directos + 54 plugins)
- MCPs: 39 (10 enabled, 29 disabled, 33 gateway, 2 locais)
- Hooks: 26 ficheiros, 9 activos
- Plugins: 14 Descomplicar + 6 oficiais + 3 terceiros, 6 activos
- CARL: 7 domínios, ~45 regras
- Paperclip: 16 operacionais
- n8n: 14 workflows
- NotebookLM: 58 notebooks
- Cache infinito (dados estáticos)
2. api/routes/ai.ts — Router Express com GET /
3. src/pages/AiOverview.tsx — Página React:
- Layout de "stack overview" com 3 secções:
a) Camada 1 (Claude Code): cards para skills, agents, MCPs, hooks, plugins
b) Camada 2 (n8n): card simples com contagem workflows
c) Camada 3 (Paperclip): card simples com contagem agentes
- Card grande central: "3 Camadas de Execução" com diagrama visual (CSS, não SVG)
- Secção CARL: 7 domínios listados (GLOBAL, CRM, DEVELOPMENT, WORDPRESS, HUB, INFRASTRUCTURE, QUALITY, SKILLS)
- Tons roxos/violeta para diferenciar das outras páginas
- Segue estilo visual do projecto
Não alteres nenhum ficheiro existente. Apenas cria os 3 novos.
```
---
## Agent E — Painel Operações
**Tipo:** `javascript-fullstack-specialist`
**Isolation:** worktree
**Ficheiros a criar:**
- `api/services/operations.ts`
- `api/routes/operations.ts`
- `src/pages/Operations.tsx`
**Prompt:**
```
Estás a trabalhar no projecto DashDescomplicar (/media/ealmeida/Dados/Dev/DashDescomplicar/).
Stack: React 19 + Vite + Tailwind CSS 4 + Express 4 + TypeScript.
Lê a spec em docs/SPEC-dashboard-expansion-q2-2026.md, secção 4.5 (Painel Operações).
A BD MySQL (Desk CRM) já tem conexão configurada em api/db.ts (export default pool mysql2/promise).
Cria 3 ficheiros:
1. api/services/operations.ts — Service que:
- Queries ao MySQL (Desk CRM):
a) Tickets abertos: SELECT COUNT(*) FROM tbltickets WHERE status IN ('Open','In Progress','Answered')
b) Tickets alta prioridade: WHERE priority IN (2,3)
c) Tickets por departamento: JOIN tbldepartments GROUP BY department
d) Tempo médio resposta: AVG(TIMESTAMPDIFF(HOUR, date, lastreply)) dos tickets com resposta
- Dados estáticos PROCs:
- 48 procedimentos, 8 departamentos
- Cobertura por dept: D1(5), D2(3), D3(3), D4(1), D5(5), D6(8), D7(18), Cross(5)
- import db from '../db.js'
2. api/routes/operations.ts — Router Express com GET /
3. src/pages/Operations.tsx — Página React:
- Stats cards: tickets abertos, alta prioridade, tempo médio resposta
- Gráfico barras horizontal (recharts BarChart): tickets por departamento
- Tabela cobertura PROCs: departamento, número PROCs, % cobertura
- Segue estilo visual: ler src/pages/Financial.tsx como referência (usa recharts)
Não alteres nenhum ficheiro existente. Apenas cria os 3 novos.
```
---
## Agent F — Coordenador / Integração (executa após A-E)
**Tipo:** `javascript-fullstack-specialist`
**Isolation:** nenhum (merge directo)
**Ficheiros a alterar:**
- `src/components/Layout.tsx`
- `src/App.tsx` (secção de routing)
- `api/server.ts` (registar routers)
**Prompt:**
```
Estás a trabalhar no projecto DashDescomplicar (/media/ealmeida/Dados/Dev/DashDescomplicar/).
Os seguintes ficheiros novos já foram criados por agentes anteriores:
- api/routes/mcps.ts, api/services/mcps.ts, src/pages/McpMonitor.tsx
- api/routes/n8n.ts, api/services/n8n.ts, src/pages/N8nMonitor.tsx
- api/routes/paperclip.ts, api/services/paperclip.ts, api/services/paperclip-db.ts, src/pages/Paperclip.tsx
- api/routes/ai.ts, api/services/ai.ts, src/pages/AiOverview.tsx
- api/routes/operations.ts, api/services/operations.ts, src/pages/Operations.tsx
Faz a integração:
1. src/components/Layout.tsx — Adicionar 5 itens ao array NAV_ITEMS:
- { 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 }
Adicionar os imports de ícones do lucide-react: Network, Workflow, Bot, Brain, ClipboardList
NOTA: verificar se 'Workflow' existe em lucide-react, se não usar 'GitBranch' ou 'Repeat'
2. src/App.tsx — Na secção de routing (BrowserRouter/Routes), adicionar:
- import McpMonitor from './pages/McpMonitor'
- import N8nMonitor from './pages/N8nMonitor'
- import Paperclip from './pages/Paperclip'
- import AiOverview from './pages/AiOverview'
- import Operations from './pages/Operations'
E as respectivas <Route> dentro do <Route element={<Layout />}>
3. api/server.ts — Adicionar imports e app.use:
- 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)
Lê cada ficheiro antes de editar. Mantém o estilo existente. Não alteres mais nada.
```
---
## Sequência de execução
```
Fase 1 (paralelo): Agent A + Agent B + Agent C + Agent D + Agent E
↓ todos concluídos
Fase 2 (sequencial): Merge worktrees → main
Fase 3 (sequencial): Agent F (integração)
Fase 4 (validação): npm run build + teste manual
```
---
## Comando conductor
```bash
# Fase 1 — lançar 5 agentes em paralelo (worktree isolation)
# Usar: Agent tool com isolation: "worktree" e run_in_background: true
# Fase 2 — após todos concluírem, merge dos worktrees
# git merge <branch-agent-a> --no-edit
# git merge <branch-agent-b> --no-edit
# ...
# Fase 3 — Agent F integração
# Sem worktree, directo no main
# Fase 4 — validar
# npm run build
# npm run dev (testar manualmente)
```
---
## Checklist de validação final
- [ ] `npm run build` sem erros
- [ ] Todas as 8 páginas navegáveis na sidebar
- [ ] GET /api/mcps retorna dados
- [ ] GET /api/n8n retorna dados (ou erro claro se API key não configurada)
- [ ] GET /api/paperclip retorna dados (ou fallback zeros se BD inacessível)
- [ ] GET /api/ai retorna dados estáticos
- [ ] GET /api/operations retorna dados do Desk CRM
- [ ] Mobile: sidebar colapsa correctamente com 8 itens
- [ ] Zero erros na consola do browser
+473
View File
@@ -0,0 +1,473 @@
---
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)