# Feature Specification: Audit Overview Dashboard (009) **Feature Branch**: `009-ops-audit-overview` **Created**: 2026-06-08 **Status**: Draft **Input**: Dashboard estilo Cloudflare Ops — health e scorecard por tenant/EmailServer (~10 nós), com 8 checks read-only alinhados ao portal onboarding. Primeira entrega do Track A (AUD-1, AUD-2, AUD-3). **Depends on**: MVP Ops VM122 (API, worker, tenants table); VM112 como primeiro tenant auditado ## User Scenarios & Testing *(mandatory)* ### User Story 1 — Overview multi-tenant (Priority: P1) A equipa ops abre `/ops/overview` (ou tab Infra expandida) e vê cards por tenant registado com estado global: OK / Atenção / Crítico. **Why this priority**: Core da visão "painel cheio de informação" — saúde de todos os nós num ecrã. **Independent Test**: Com VM112 registada, overview mostra card com score 6/8 checks OK. **Acceptance Scenarios**: 1. **Given** tenant VM112 com todos checks verdes, **When** overview carrega, **Then** card mostra `healthy` e score `8/8`. 2. **Given** check DKIM falhou, **When** overview carrega, **Then** card mostra `degraded` e lista check falhado. 3. **Given** tenant API inacessível, **When** collector falha, **Then** card mostra `unknown` com timestamp última tentativa. --- ### User Story 2 — Scorecard 8 checks por domínio (Priority: P1) Por tenant, a equipa vê detalhe dos 8 checks alinhados ao wizard portal: Carbonio, nginx/vhost, certificado LE, MX, SPF, DKIM, DMARC, webmail HTTP. **Why this priority**: Diagnóstico actionable — sabe exactamente o que corrigir sem SSH manual. **Independent Test**: Abrir scorecard VM112 para `diarissima.com` (ou domínio activo) e ver 8 linhas com pass/fail. **Acceptance Scenarios**: 1. **Given** domínio com SPF correcto, **When** scorecard renderiza, **Then** check `spf` = pass com valor detectado. 2. **Given** certificado expira em < 14 dias, **When** scorecard renderiza, **Then** check `cert` = warn. 3. **Given** webmail responde HTTP 200, **When** check `webmail`, **Then** pass com URL testada. --- ### User Story 3 — Collectors automáticos (Priority: P1) Worker Ops executa collectors read-only periodicamente (sem alterar sistemas remotos) e persiste snapshots. **Why this priority**: Dados frescos sem refresh manual; base para alertas futuros. **Independent Test**: Após ciclo worker (≤ 15 min), `GET /api/v1/audit/overview` reflecte dados novos. **Acceptance Scenarios**: 1. **Given** worker activo, **When** passam 10 minutos, **Then** `last_audit_at` actualiza. 2. **Given** collector DNS timeout, **When** falha, **Then** check marcado `error` com mensagem; outros checks continuam. --- ### User Story 4 — Domínios monitorizados (Priority: P2) Cada tenant pode ter 1+ domínios monitorizados (inicialmente domínios vistos em eventos onboarding ou lista manual). **Why this priority**: EmailServers multi-domínio; MVP pode começar com domínio principal do tenant. **Independent Test**: Domínio de evento `account.created` aparece automaticamente em scorecard. **Acceptance Scenarios**: 1. **Given** evento `account.created` para `foo.com`, **When** próximo audit cycle, **Then** `foo.com` entra em domínios monitorizados do tenant VM112. --- ### Edge Cases - Tenant sem domínios conhecidos: scorecard vazio com hint "aguardar onboarding". - Check intermitente (DNS): último resultado + contagem falhas consecutivas. - VM112 portal down: checks locais Carbonio via API read-only falham gracefully. - Múltiplos tenants (futuro 10 nós): overview pagina ou scroll; MVP suporta ≥ 3. ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: Ops DEVE expor `GET /api/v1/audit/overview` — lista tenants com status agregado e score. - **FR-002**: Ops DEVE expor `GET /api/v1/audit/tenants/{id}/scorecard?domain=` — 8 checks detalhados. - **FR-003**: Worker DEVE executar collectors a cada `AUDIT_INTERVAL_SEC` (default 600s). - **FR-004**: Collectors DEVEM ser read-only — sem zmprov write, sem alterar DNS/Traefik. - **FR-005**: Os 8 checks MVP: `carbonio`, `nginx_vhost`, `cert_le`, `dns_mx`, `dns_spf`, `dns_dkim`, `dns_dmarc`, `webmail_http`. - **FR-006**: Resultado por check: `pass` | `warn` | `fail` | `error` | `skip` + `message` + `checked_at`. - **FR-007**: Persistência em SQLite: tabelas `audit_domains`, `audit_checks` (último snapshot por tenant+domain+check). - **FR-008**: UI DEVE ter view **Overview** (ou expandir Infra) com grid de cards tenant. - **FR-009**: UI DEVE permitir drill-down scorecard por tenant/domínio. - **FR-010**: Domínios auto-registados a partir de eventos webhook `account.created` / `onboarding.completed`. - **FR-011**: VM112 primeiro tenant: collectors usam API portal read-only (`/onboarding/infrastructure/status/{domain}`, `/dns/verify/{domain}`) + HTTP externo DNS/webmail. ### Key Entities - **Audit Domain**: tenant_id, domain, source (`onboarding` | `manual`), added_at. - **Audit Check**: check_id, status, message, evidence (JSON), checked_at. - **Tenant Health**: aggregated from worst check status. ### Status aggregation rules | Pior check | Tenant status | |------------|---------------| | fail | critical | | error | critical | | warn | degraded | | pass/skip | healthy | ## Success Criteria *(mandatory)* - **SC-001**: Overview carrega em < 2s com 3 tenants e 5 domínios. - **SC-002**: 8/8 checks executados para domínio activo VM112 em ciclo worker. - **SC-003**: Equipa identifica problema deliverability (SPF/DKIM/DMARC) via scorecard sem SSH. - **SC-004**: Dados actualizados automaticamente ≤ 15 min (configurável). - **SC-005**: Zero writes em sistemas remotos durante audit (verificável por logs). ## Assumptions - VM112 portal API acessível na LAN `:8090` (já usado por `vm112/status`). - Checks DNS via resolver público (8.8.8.8) ou biblioteca dns.resolver — read-only. - Webmail check: HEAD/GET `https://mail.{domain}/` timeout 10s. - Cert check: expiry via portal infra status ou TLS handshake directo. - Postgres não necessário — SQLite suficiente para MVP. - Agentes IA (AUD-4) fora de scope — só collectors determinísticos. ## Dependencies - Constitution v1.0.0 - Tenant registry (tabela `tenants` existente) - Worker Redis container existente em VM122 - Feature 004 opcional (auto-domínios) — pode usar só `account.created` events já existentes ## Out of Scope - Agentes IA A1/A2/A3 (AUD-4, AUD-5) - Alterações automáticas / remediation - Poll Wazuh API - Auth RBAC (003) - Alertas email/ntfy por check fail - 10 tenants hardcoded — registo manual OK para MVP além de VM112 ## The 8 Checks (aligned portal) | ID | Check | Fonte read-only | |----|-------|-----------------| | 1 | carbonio | Portal ou zmprov read via API VM112 | | 2 | nginx_vhost | `infrastructure/status` → carbonio_nginx_vhost | | 3 | cert_le | infra status → cert expiry | | 4 | dns_mx | DNS lookup MX → mail.{domain} | | 5 | dns_spf | DNS TXT SPF | | 6 | dns_dkim | DNS TXT default._domainkey | | 7 | dns_dmarc | DNS TXT _dmarc | | 8 | webmail_http | HTTPS mail.{domain} status code |