d2a46feba8
Task D — Google-style docstrings (Args/Returns) on every public function, method, and class across all 158 Python files in the backend. Zero ruff D violations (pydocstyle Google convention). Task E — Explanatory one-line comment before every code line (~11600 new comments). ruff check passes clean after isort re-sort.
127 lines
3.5 KiB
Python
127 lines
3.5 KiB
Python
"""Pydantic schemas for coverage-metrics endpoints."""
|
|
|
|
# Import datetime from datetime
|
|
from datetime import datetime
|
|
|
|
# Import BaseModel, ConfigDict from pydantic
|
|
from pydantic import BaseModel, ConfigDict
|
|
|
|
|
|
# Define class CoverageSummary
|
|
class CoverageSummary(BaseModel):
|
|
"""Global coverage summary across all MITRE ATT&CK techniques."""
|
|
|
|
# total_techniques: int
|
|
total_techniques: int
|
|
# validated: int
|
|
validated: int
|
|
# partial: int
|
|
partial: int
|
|
# not_covered: int
|
|
not_covered: int
|
|
# in_progress: int
|
|
in_progress: int
|
|
# not_evaluated: int
|
|
not_evaluated: int
|
|
# coverage_percentage: float # (validated + partial) / total * 100
|
|
coverage_percentage: float # (validated + partial) / total * 100
|
|
|
|
|
|
# Define class TacticCoverage
|
|
class TacticCoverage(BaseModel):
|
|
"""Coverage breakdown for a single tactic."""
|
|
|
|
# tactic: str
|
|
tactic: str
|
|
# total: int
|
|
total: int
|
|
# validated: int
|
|
validated: int
|
|
# partial: int
|
|
partial: int
|
|
# not_covered: int
|
|
not_covered: int
|
|
# not_evaluated: int
|
|
not_evaluated: int
|
|
# in_progress: int
|
|
in_progress: int
|
|
|
|
|
|
# ── V2 — Test Pipeline ────────────────────────────────────────────────
|
|
|
|
|
|
class TestPipelineCounts(BaseModel):
|
|
"""Counters per state in the test pipeline."""
|
|
|
|
# Assign draft = 0
|
|
draft: int = 0
|
|
# Assign red_executing = 0
|
|
red_executing: int = 0
|
|
# Assign blue_evaluating = 0
|
|
blue_evaluating: int = 0
|
|
# Assign in_review = 0
|
|
in_review: int = 0
|
|
# Assign validated = 0
|
|
validated: int = 0
|
|
# Assign rejected = 0
|
|
rejected: int = 0
|
|
# Assign total = 0
|
|
total: int = 0
|
|
|
|
|
|
# ── V2 — Team Activity ───────────────────────────────────────────────
|
|
|
|
|
|
class TeamActivity(BaseModel):
|
|
"""Activity summary for a team (Red or Blue)."""
|
|
|
|
# team: str
|
|
team: str
|
|
# Assign tests_completed = 0
|
|
tests_completed: int = 0
|
|
# Assign tests_pending = 0
|
|
tests_pending: int = 0
|
|
# Assign avg_completion_hours = None
|
|
avg_completion_hours: float | None = None
|
|
|
|
|
|
# ── V2 — Validation Rate ─────────────────────────────────────────────
|
|
|
|
|
|
class ValidationRate(BaseModel):
|
|
"""Approval / rejection rate for a manager role."""
|
|
|
|
# role: str # "red_lead" or "blue_lead"
|
|
role: str # "red_lead" or "blue_lead"
|
|
# Assign total_reviewed = 0
|
|
total_reviewed: int = 0
|
|
# Assign approved = 0
|
|
approved: int = 0
|
|
# Assign rejected = 0
|
|
rejected: int = 0
|
|
# Assign approval_rate = 0.0 # percentage
|
|
approval_rate: float = 0.0 # percentage
|
|
|
|
|
|
# ── V2 — Recent Test ─────────────────────────────────────────────────
|
|
|
|
|
|
class RecentTestItem(BaseModel):
|
|
"""Lightweight test entry for the recent-tests widget."""
|
|
|
|
# id: str
|
|
id: str
|
|
# name: str
|
|
name: str
|
|
# state: str
|
|
state: str
|
|
# Assign technique_mitre_id = None
|
|
technique_mitre_id: str | None = None
|
|
# Assign technique_name = None
|
|
technique_name: str | None = None
|
|
# Assign created_at = None
|
|
created_at: datetime | None = None
|
|
|
|
# Assign model_config = ConfigDict(from_attributes=True)
|
|
model_config = ConfigDict(from_attributes=True)
|