feat(cra): cyber-meets-safety bridge as real logic (step 2)
Deterministic bridge (cra_safety_bridge.py): a cyber finding's attack capability (remote_actuation / code_tampering / integrity_loss / auth_bypass, derived from its CRA category) is matched against what each CE safety function is vulnerable to. A match re-opens the mitigated hazard, flags the finding safety_impact (which floors it to P0), and produces the cross-link. Endpoint accepts safety_functions; frontend passes the project's safety functions and renders the LIVE cross-links (no more hardcode). Safety functions are demo input now; come from the CE risk assessment in production. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,24 @@ import { CRADemo, CRAFinding, Measure, DEMO_SCENARIO } from './useCRADemo'
|
||||
|
||||
export type Weights = Record<string, string> // objective -> high|medium|low
|
||||
|
||||
// Demo: CE-risk-assessment safety functions of the Kistenhub (would come from the
|
||||
// project's CE risk assessment in production). The backend bridge decides which
|
||||
// cyber findings can defeat them (and flags those safety_impact -> P0).
|
||||
const SAFETY_FUNCTIONS = [
|
||||
{
|
||||
name: 'Zweihandschaltung + trennende Schutzeinrichtung am Hubwerk',
|
||||
hazard: 'Unerwarteter Anlauf des Hubwerks → Quetschen zwischen Last und Rahmen',
|
||||
original_measure: 'Zweihandschaltung + trennende Schutzeinrichtung (mechanisch, PL d)',
|
||||
kind: 'prevent_unexpected_actuation',
|
||||
},
|
||||
{
|
||||
name: 'Überlastsicherung / Lastmomentbegrenzer',
|
||||
hazard: 'Überlast / Lastabsturz durch manipulierte Lastgrenze',
|
||||
original_measure: 'Überlastsicherung / Lastmomentbegrenzer',
|
||||
kind: 'signal_integrity',
|
||||
},
|
||||
]
|
||||
|
||||
function reqTitle(rationale: string): string {
|
||||
const i = rationale.indexOf(': ')
|
||||
return i >= 0 ? rationale.slice(i + 2) : rationale
|
||||
@@ -54,7 +72,7 @@ function merge(live: any): CRADemo {
|
||||
coverage_pct: live.coverage_pct ?? DEMO_SCENARIO.coverage_pct,
|
||||
requirements_touched: live.requirements_touched || DEMO_SCENARIO.requirements_touched,
|
||||
open_measures,
|
||||
cross_links: DEMO_SCENARIO.cross_links,
|
||||
cross_links: live.cross_links && live.cross_links.length ? live.cross_links : DEMO_SCENARIO.cross_links,
|
||||
deadlines: live.deadlines || DEMO_SCENARIO.deadlines,
|
||||
quick_wins: live.quick_wins || [],
|
||||
objectives: live.objectives || [],
|
||||
@@ -71,10 +89,10 @@ export function useCRA() {
|
||||
const payload = {
|
||||
findings: DEMO_SCENARIO.findings.map((f) => ({
|
||||
id: f.id, title: f.title, cwe: f.cwe, severity: f.scanner_severity, location: f.location,
|
||||
// demo: flag the two findings tied to a safety cross-link as safety_impact
|
||||
safety_impact: f.id === 'KH-CY-1' || f.id === 'KH-CY-2' || f.id === 'KH-CY-3',
|
||||
})),
|
||||
weights,
|
||||
// the bridge decides safety_impact from these (no frontend hardcode)
|
||||
safety_functions: SAFETY_FUNCTIONS,
|
||||
}
|
||||
fetch('/api/v1/cra/assess', {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user