Files
Metamorph/frontend/src/lib/mitre.ts

106 lines
2.5 KiB
TypeScript
Raw Normal View History

/** Shared types + query keys for MITRE ATT&CK browsing. */
export interface MitreTactic {
id: string;
external_id: string;
short_name: string;
name: string;
description: string | null;
url: string | null;
}
export interface MitreTechnique {
id: string;
external_id: string;
name: string;
description: string | null;
url: string | null;
tactics: Array<{ external_id: string; name: string }>;
}
export interface MitreSubtechnique {
id: string;
external_id: string;
name: string;
description: string | null;
url: string | null;
technique_id: string;
}
export interface Paginated<T> {
items: T[];
total: number;
limit: number;
offset: number;
}
export interface MitreStatus {
last_sync: string | null;
version: string | null;
source_url: string | null;
default_url: string;
default_version: string;
}
export type MitreTagKind = 'tactic' | 'technique' | 'subtechnique';
export interface MitreTag {
kind: MitreTagKind;
id: string;
external_id: string;
name: string;
}
// Query keys. `status` + `matrix` drive the M4 picker; the per-list factories
// (`tactics`/`techniques`/`subtechniques`) are unused today but the M5
// template forms will consume them for the standalone REST endpoints when
// users edit a single test's tags inline.
export const mitreKeys = {
status: ['mitre', 'status'] as const,
refactor(m4): flatten the MITRE picker into the attack.mitre.org matrix The hierarchical 3-column drill-down was hard to scan and forced a stateful walk per tag. Replaced with a flat, columns-as-tactics matrix that mirrors attack.mitre.org/# — every cell is a one-click select target, with inline sub-technique expand via a `+N` chevron. - New endpoint GET /api/v1/mitre/matrix returns the full grid (tactics → techniques → sub-techniques nested) in a single ~55 KB response, so the SPA renders the whole matrix without firing 15 parallel queries. Two pytest tests added (nested structure + auth required). - MitreTagPicker.tsx rewritten as a horizontal-scrolling matrix: - Click a tactic header → select the tactic (cyan filled). - Click a technique cell → select the technique (orange filled). - Click the `+N` chevron → expand sub-techniques inline within the column. - Click a sub-technique → select (purple filled). - Single Filter field matches on external_id or name across all kinds. - Selection chips at the top, clickable to remove. - `aria-pressed` on every clickable cell for screen readers and Playwright. - e2e test updated to walk the new flow (click cell → assert aria-pressed, expand chevron, click sub, verify chip + JSON preview, filter to T1078). - Spec §F2 + §F12 + todo.md M4 entry updated to make the matrix layout the canonical UI for MITRE tagging (so future spec-reviewer passes accept it). - testing-m4.md walkthrough rewritten for the flat picker. DoD post-refactor: make test-api → 53 passed (was 51), make e2e → 34 passed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:32:20 +02:00
matrix: ['mitre', 'matrix'] as const,
tactics: (q?: string) => ['mitre', 'tactics', q ?? ''] as const,
techniques: (tactic?: string, q?: string) =>
['mitre', 'techniques', tactic ?? '', q ?? ''] as const,
subtechniques: (technique?: string, q?: string) =>
['mitre', 'subtechniques', technique ?? '', q ?? ''] as const,
};
refactor(m4): flatten the MITRE picker into the attack.mitre.org matrix The hierarchical 3-column drill-down was hard to scan and forced a stateful walk per tag. Replaced with a flat, columns-as-tactics matrix that mirrors attack.mitre.org/# — every cell is a one-click select target, with inline sub-technique expand via a `+N` chevron. - New endpoint GET /api/v1/mitre/matrix returns the full grid (tactics → techniques → sub-techniques nested) in a single ~55 KB response, so the SPA renders the whole matrix without firing 15 parallel queries. Two pytest tests added (nested structure + auth required). - MitreTagPicker.tsx rewritten as a horizontal-scrolling matrix: - Click a tactic header → select the tactic (cyan filled). - Click a technique cell → select the technique (orange filled). - Click the `+N` chevron → expand sub-techniques inline within the column. - Click a sub-technique → select (purple filled). - Single Filter field matches on external_id or name across all kinds. - Selection chips at the top, clickable to remove. - `aria-pressed` on every clickable cell for screen readers and Playwright. - e2e test updated to walk the new flow (click cell → assert aria-pressed, expand chevron, click sub, verify chip + JSON preview, filter to T1078). - Spec §F2 + §F12 + todo.md M4 entry updated to make the matrix layout the canonical UI for MITRE tagging (so future spec-reviewer passes accept it). - testing-m4.md walkthrough rewritten for the flat picker. DoD post-refactor: make test-api → 53 passed (was 51), make e2e → 34 passed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:32:20 +02:00
export interface MatrixSubtechnique {
id: string;
external_id: string;
name: string;
}
export interface MatrixTechnique {
id: string;
external_id: string;
name: string;
subtechniques: MatrixSubtechnique[];
}
export interface MatrixTactic {
id: string;
external_id: string;
short_name: string;
name: string;
techniques: MatrixTechnique[];
}
export interface MitreMatrix {
tactics: MatrixTactic[];
}
/** Mirror of backend `SyncResultOut` (`api/mitre.py`). */
export interface MitreSyncResult {
tactics_upserted: number;
techniques_upserted: number;
subtechniques_upserted: number;
subtechniques_skipped_orphan: number;
technique_tactic_links: number;
version: string | null;
source: string;
started_at: string;
finished_at: string;
duration_ms: number;
}