feat(phase-28): add scoring system, operational metrics and executive dashboard (T-224 to T-226)

This commit is contained in:
2026-02-09 17:24:44 +01:00
parent a911ddeb52
commit 12f33307fd
11 changed files with 1930 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
import client from "./client";
// ── Types ────────────────────────────────────────────────────────────
export interface MTTDMetric {
mean_hours: number;
median_hours: number;
min_hours: number;
max_hours: number;
sample_size: number;
}
export interface MTTRMetric {
mean_hours: number;
median_hours: number;
min_hours: number;
max_hours: number;
sample_size: number;
}
export interface DetectionEfficacy {
percentage: number;
detected: number;
partially: number;
not_detected: number;
total: number;
}
export interface AlertFidelity {
percentage: number;
triggered: number;
not_triggered: number;
total_evaluated: number;
}
export interface CoverageVelocity {
techniques_per_week: number;
trend: "improving" | "declining" | "stable";
}
export interface ValidationThroughput {
tests_per_week: number;
trend: "improving" | "declining" | "stable";
}
export interface RejectionRate {
percentage: number;
by_red_lead: number;
by_blue_lead: number;
}
export interface OperationalMetrics {
mttd: MTTDMetric | null;
mttr: MTTRMetric | null;
detection_efficacy: DetectionEfficacy;
alert_fidelity: AlertFidelity;
coverage_velocity: CoverageVelocity;
validation_throughput: ValidationThroughput;
rejection_rate: RejectionRate;
}
export interface OperationalTrendPoint {
date: string;
detection_efficacy: number;
validated_tests: number;
detected_tests: number;
}
export interface TeamMetrics {
red_team: {
tests_completed: number;
avg_completion_hours: number | null;
rejection_rate: number;
};
blue_team: {
tests_completed: number;
avg_completion_hours: number | null;
rejection_rate: number;
};
}
// ── API Functions ────────────────────────────────────────────────────
export async function getOperationalMetrics(): Promise<OperationalMetrics> {
const { data } = await client.get<OperationalMetrics>("/metrics/operational");
return data;
}
export async function getOperationalTrend(
period: string = "90d",
): Promise<OperationalTrendPoint[]> {
const { data } = await client.get<OperationalTrendPoint[]>("/metrics/operational/trend", {
params: { period },
});
return data;
}
export async function getMetricsByTeam(): Promise<TeamMetrics> {
const { data } = await client.get<TeamMetrics>("/metrics/operational/by-team");
return data;
}