feat(phase-13): update frontend types and API clients for Red/Blue workflow (T-113, T-114)

T-113: Rewrite models.ts with v2 types - TestState now includes red_executing/blue_evaluating, add TeamSide, ValidationStatus, TestTemplate, TestTemplateSummary, TestTimelineEntry types, RED_EDITABLE_STATES/BLUE_EDITABLE_STATES constants, and dual validation fields on Test interface. Remove old validated_by/validated_at references from TestDetailPage and techniques API.

T-114: Rewrite tests.ts API client with 16 functions covering full Red/Blue workflow (createTestFromTemplate, updateTestRed/Blue, startExecution, submitRed/Blue, validateAsRedLead/BlueLead, reopenTest, getTestTimeline). Rewrite evidence.ts with team parameter on upload/list and new deleteEvidence. Create test-templates.ts with getTemplates, getTemplateById, getTemplatesByTechnique, createTemplate, importAtomicTests.
This commit is contained in:
2026-02-09 10:57:48 +01:00
parent 9d7832c571
commit d660bceeb4
6 changed files with 447 additions and 68 deletions

View File

@@ -1,11 +1,15 @@
/* ── Shared TypeScript types matching the backend Pydantic schemas ── */
// ── Users ──────────────────────────────────────────────────────────
export interface User {
id: string;
username: string;
role: string;
}
// ── Techniques ─────────────────────────────────────────────────────
export interface Technique {
id: string;
mitre_id: string;
@@ -30,6 +34,28 @@ export type TechniqueStatus =
| "not_covered"
| "review_required";
// ── Tests (v2 — Red/Blue dual validation) ──────────────────────────
export type TestState =
| "draft"
| "red_executing"
| "blue_evaluating"
| "in_review"
| "validated"
| "rejected";
export type TestResult = "detected" | "not_detected" | "partially_detected";
export type ValidationStatus = "pending" | "approved" | "rejected";
export type TeamSide = "red" | "blue";
/** States in which Red Team can edit / upload evidence. */
export const RED_EDITABLE_STATES: TestState[] = ["draft", "red_executing"];
/** States in which Blue Team can edit / upload evidence. */
export const BLUE_EDITABLE_STATES: TestState[] = ["blue_evaluating"];
export interface Test {
id: string;
technique_id: string;
@@ -42,13 +68,30 @@ export interface Test {
created_by: string | null;
result: TestResult | null;
state: TestState;
validated_by: string | null;
validated_at: string | null;
created_at: string;
// Red Team fields
red_summary: string | null;
attack_success: boolean | null;
red_validated_by: string | null;
red_validated_at: string | null;
red_validation_status: ValidationStatus | null;
red_validation_notes: string | null;
// Blue Team fields
blue_summary: string | null;
detection_result: TestResult | null;
blue_validated_by: string | null;
blue_validated_at: string | null;
blue_validation_status: ValidationStatus | null;
blue_validation_notes: string | null;
// Separated evidences
red_evidences: Evidence[];
blue_evidences: Evidence[];
}
export type TestState = "draft" | "in_review" | "validated" | "rejected";
export type TestResult = "detected" | "not_detected" | "partially_detected";
// ── Evidence (v2 — with team) ──────────────────────────────────────
export interface Evidence {
id: string;
@@ -58,8 +101,51 @@ export interface Evidence {
sha256_hash: string;
uploaded_by: string | null;
uploaded_at: string;
team: TeamSide;
notes: string | null;
download_url?: string;
}
// ── Test Templates ─────────────────────────────────────────────────
export interface TestTemplate {
id: string;
mitre_technique_id: string;
name: string;
description: string | null;
source: string;
source_url: string | null;
attack_procedure: string | null;
expected_detection: string | null;
platform: string | null;
tool_suggested: string | null;
severity: string | null;
atomic_test_id: string | null;
is_active: boolean;
created_at: string;
}
export interface TestTemplateSummary {
id: string;
mitre_technique_id: string;
name: string;
source: string;
platform: string | null;
severity: string | null;
}
// ── Timeline ───────────────────────────────────────────────────────
export interface TestTimelineEntry {
id: string;
action: string;
user_id: string | null;
timestamp: string;
details: Record<string, unknown>;
}
// ── Intel ──────────────────────────────────────────────────────────
export interface IntelItem {
id: string;
technique_id: string | null;
@@ -70,6 +156,8 @@ export interface IntelItem {
reviewed: boolean;
}
// ── Metrics ────────────────────────────────────────────────────────
export interface CoverageSummary {
total_techniques: number;
validated: number;