feat(iace): project-wide risk matrix (Severity × Probability)
Adds GET /projects/:id/risk-matrix — a confidence-aware risk view computed on read from each hazard's category/scenario/lifecycle using the SAME model as the GT benchmark (no persistence, so it never goes stale against the model; the hand-defaulted iace_hazards risk columns stay untouched). - risk_matrix.go: EstimateHazardRisk (single source of truth for S/F/W/P + range + level + confidence) and BuildRiskMatrix (per-hazard list + a 5×5 Severity×Probability aggregation grid with dominant level per cell). - Frontend: RiskMatrix grid in the Risikobewertung tab (muted colours per the confidence-aware tonality), level counts + tool-confidence summary, fed by useRiskMatrix. Shows risk for EVERY project, not only GT ones. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export interface HazardRiskDetail {
|
||||
hazard_id: string
|
||||
name: string
|
||||
category: string
|
||||
zone: string
|
||||
severity: number
|
||||
frequency: number
|
||||
probability: number
|
||||
avoidance: number
|
||||
risk_point: number
|
||||
risk_low: number
|
||||
risk_high: number
|
||||
level: string
|
||||
level_range: string
|
||||
confidence: string
|
||||
}
|
||||
|
||||
export interface RiskMatrixCell {
|
||||
severity: number
|
||||
probability: number
|
||||
count: number
|
||||
dominant_level: string
|
||||
hazard_ids: string[]
|
||||
}
|
||||
|
||||
export interface RiskMatrixData {
|
||||
hazards: HazardRiskDetail[]
|
||||
matrix: RiskMatrixCell[]
|
||||
level_counts: Record<string, number>
|
||||
total: number
|
||||
high_confidence_pct: number
|
||||
}
|
||||
|
||||
/** Loads the project-wide confidence-aware risk matrix (computed server-side). */
|
||||
export function useRiskMatrix(projectId: string) {
|
||||
const [data, setData] = useState<RiskMatrixData | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
async function load() {
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/risk-matrix`)
|
||||
const json = res.ok ? ((await res.json()) as RiskMatrixData) : null
|
||||
if (!cancelled) setData(json)
|
||||
} catch (err) {
|
||||
console.error('Failed to load risk matrix:', err)
|
||||
} finally {
|
||||
if (!cancelled) setLoading(false)
|
||||
}
|
||||
}
|
||||
load()
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [projectId])
|
||||
|
||||
return { data, loading }
|
||||
}
|
||||
Reference in New Issue
Block a user