158 lines
7 KiB
Markdown
158 lines
7 KiB
Markdown
# 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 |
|