feat(cra): NIST/OWASP security golden-set crosswalk + full measure texts in CRA tab
Crosswalk (cra_security_crosswalk.py): deterministic, hand-curated CRA Annex I -> NIST 800-53 Rev5 + OWASP Top 10:2021 mapping, the authoritative Security Golden Set (no RAG; semantic breadth comes later via the shared Controls-API). Mapper attaches NIST/OWASP refs per finding; golden-set completeness pinned by test (every requirement has >=1 NIST ref). CRA tab now shows the NIST/OWASP best- practice refs per finding and the full curated measure texts + norm references (from measures_library_cra.go). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -92,7 +92,7 @@ export function CRACyberView({ data }: { data: CRADemo }) {
|
||||
<tr className="text-gray-500 border-b border-gray-200 dark:border-gray-700 text-left">
|
||||
<th className="py-2 px-4">Cyber-Befund</th>
|
||||
<th className="py-2 px-3">CRA-Anforderung</th>
|
||||
<th className="py-2 px-3">Annex I</th>
|
||||
<th className="py-2 px-3">Best Practice (NIST / OWASP)</th>
|
||||
<th className="py-2 px-3">Risiko</th>
|
||||
<th className="py-2 px-4">Maßnahmen</th>
|
||||
</tr>
|
||||
@@ -109,11 +109,25 @@ export function CRACyberView({ data }: { data: CRADemo }) {
|
||||
{f.requirement_ids.length > 1 && (
|
||||
<span className="text-[10px] text-gray-400"> +{f.requirement_ids.length - 1}</span>
|
||||
)}
|
||||
<div className="text-[10px] text-gray-400">{f.annex_anchor}</div>
|
||||
</td>
|
||||
<td className="py-2 px-3">
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{f.nist_refs.map((n) => (
|
||||
<span key={n} className="inline-block rounded bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-300 px-1.5 py-0.5 text-[10px] font-mono">
|
||||
{n}
|
||||
</span>
|
||||
))}
|
||||
{f.owasp_refs.map((o) => (
|
||||
<span key={o.code} title={o.label} className="inline-block rounded bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300 px-1.5 py-0.5 text-[10px] font-medium">
|
||||
{o.code}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</td>
|
||||
<td className="py-2 px-3 text-gray-500">{f.annex_anchor}</td>
|
||||
<td className="py-2 px-3"><RiskBadge level={f.risk_level} /></td>
|
||||
<td className="py-2 px-4 text-gray-600 dark:text-gray-300">
|
||||
{f.measures.length ? f.measures.map((me) => me.id).join(', ') : <span className="text-gray-400">—</span>}
|
||||
{f.measures.length ? f.measures.join(', ') : <span className="text-gray-400">—</span>}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
@@ -122,29 +136,40 @@ export function CRACyberView({ data }: { data: CRADemo }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Measures + deadlines */}
|
||||
<div className="grid md:grid-cols-2 gap-3">
|
||||
<div className="rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-4">
|
||||
<h2 className="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-2">Empfohlene Maßnahmen</h2>
|
||||
<ul className="space-y-1.5">
|
||||
{data.open_measures.map((me) => (
|
||||
<li key={me.id} className="text-xs text-gray-600 dark:text-gray-300">
|
||||
<span className="font-medium text-gray-700 dark:text-gray-200">{me.id}</span> — {me.description}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-4">
|
||||
<h2 className="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-2">CRA-Fristen</h2>
|
||||
<ul className="space-y-1.5">
|
||||
{data.deadlines.map((d) => (
|
||||
<li key={d.date} className="text-xs text-gray-600 dark:text-gray-300 flex gap-2">
|
||||
<span className="font-mono text-gray-500">{d.date}</span> {d.label}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{/* Recommended measures — full curated text + norm references */}
|
||||
<div className="rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-4">
|
||||
<h2 className="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-1">Empfohlene Maßnahmen</h2>
|
||||
<p className="text-[11px] text-gray-400 mb-3">Kuratierte CRA-Maßnahmen aus der BreakPilot-Bibliothek — mit Normverweisen.</p>
|
||||
<div className="space-y-3">
|
||||
{data.open_measures.map((me) => (
|
||||
<div key={me.id} className="rounded-lg border border-gray-100 dark:border-gray-700/60 p-3">
|
||||
<p className="text-sm font-medium text-gray-800 dark:text-gray-200">
|
||||
<span className="font-mono text-purple-600 dark:text-purple-400">{me.id}</span> — {me.name}
|
||||
</p>
|
||||
<p className="text-xs text-gray-600 dark:text-gray-300 mt-1">{me.description}</p>
|
||||
<div className="flex flex-wrap gap-1 mt-2">
|
||||
{me.norm_refs.map((nr) => (
|
||||
<span key={nr} className="inline-block rounded bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-300 px-1.5 py-0.5 text-[10px]">
|
||||
{nr}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CRA deadlines */}
|
||||
<div className="rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-4">
|
||||
<h2 className="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-2">CRA-Fristen</h2>
|
||||
<ul className="flex flex-wrap gap-4">
|
||||
{data.deadlines.map((d) => (
|
||||
<li key={d.date} className="text-xs text-gray-600 dark:text-gray-300 flex items-center gap-2">
|
||||
<span className="font-mono text-gray-500">{d.date}</span> {d.label}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user