feat(dashboard): Phase 13 — Executive Dashboard
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
PostureSnapshot model, Alembic migration (b039exec), schemas, service aggregating all phases (coverage/risk/operations/knowledge/MTTD), and router at /api/v1/dashboard with executive view, KPIs, coverage-by-tactic, posture-history, posture-snapshot, and activity-feed endpoints. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
113
backend/app/schemas/executive_dashboard_schema.py
Normal file
113
backend/app/schemas/executive_dashboard_schema.py
Normal file
@@ -0,0 +1,113 @@
|
||||
"""Phase 13: Executive Dashboard — Pydantic schemas."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class PostureSnapshotOut(BaseModel):
|
||||
id: UUID
|
||||
snapshot_date: date
|
||||
|
||||
# Coverage
|
||||
total_techniques: int
|
||||
validated_count: int
|
||||
partial_count: int
|
||||
not_covered_count: int
|
||||
coverage_pct: float
|
||||
|
||||
# Risk
|
||||
avg_risk_score: float
|
||||
critical_count: int
|
||||
high_count: int
|
||||
medium_count: int
|
||||
low_count: int
|
||||
|
||||
# Operations
|
||||
open_queue_items: int
|
||||
orphan_techniques: int
|
||||
|
||||
# Knowledge
|
||||
playbook_count: int
|
||||
lesson_count: int
|
||||
|
||||
# MTTD
|
||||
mttd_avg_seconds: Optional[float] = None
|
||||
executions_30d: int
|
||||
detection_rate_30d: Optional[float] = None
|
||||
|
||||
# Meta
|
||||
created_by: Optional[UUID] = None
|
||||
created_at: Optional[datetime] = None
|
||||
extra: Optional[Dict[str, Any]] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ExecutiveSummary(BaseModel):
|
||||
"""Full executive view — current posture + trends."""
|
||||
snapshot: PostureSnapshotOut
|
||||
coverage_trend: List[Dict[str, Any]] = Field(
|
||||
default_factory=list,
|
||||
description="Last 30-day coverage_pct series [{date, value}]",
|
||||
)
|
||||
risk_trend: List[Dict[str, Any]] = Field(
|
||||
default_factory=list,
|
||||
description="Last 30-day avg_risk_score series [{date, value}]",
|
||||
)
|
||||
top_risks: List[Dict[str, Any]] = Field(
|
||||
default_factory=list,
|
||||
description="Top 5 highest-risk techniques",
|
||||
)
|
||||
coverage_by_tactic: List[Dict[str, Any]] = Field(
|
||||
default_factory=list,
|
||||
description="Per-tactic validated/partial/not_covered counts",
|
||||
)
|
||||
recent_activity: List[Dict[str, Any]] = Field(
|
||||
default_factory=list,
|
||||
description="Most-recent events (tests, paths, queue changes)",
|
||||
)
|
||||
|
||||
|
||||
class KpiBlock(BaseModel):
|
||||
"""Compact KPI block for a dashboard header."""
|
||||
coverage_pct: float
|
||||
avg_risk_score: float
|
||||
critical_count: int
|
||||
open_queue_items: int
|
||||
orphan_techniques: int
|
||||
mttd_avg_seconds: Optional[float] = None
|
||||
detection_rate_30d: Optional[float] = None
|
||||
playbook_count: int
|
||||
lesson_count: int
|
||||
snapshot_date: date
|
||||
snapshot_id: UUID
|
||||
|
||||
|
||||
class CoverageByTactic(BaseModel):
|
||||
tactic: str
|
||||
total: int
|
||||
validated: int
|
||||
partial: int
|
||||
not_covered: int
|
||||
coverage_pct: float
|
||||
|
||||
|
||||
class PostureHistoryEntry(BaseModel):
|
||||
snapshot_date: date
|
||||
coverage_pct: float
|
||||
avg_risk_score: float
|
||||
critical_count: int
|
||||
open_queue_items: int
|
||||
|
||||
|
||||
class ActivityEntry(BaseModel):
|
||||
ts: datetime
|
||||
category: str # "test" | "attack_path" | "queue" | "osint"
|
||||
title: str
|
||||
detail: Optional[str] = None
|
||||
Reference in New Issue
Block a user