feat(compliance): executive descriptions and mapping rationale for all 5 frameworks
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Backend: expose description in control status response, add rich business-language descriptions to all curated controls (ISO 27001, ISO 42001, CIS v8, DORA) explaining requirements and ATT&CK mapping rationale. ISO 42001 includes infrastructure-mapping note. Frontend: description field in type, info panel in ControlsTable expanded rows, framework info banner with description and official standard link in CompliancePage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { Loader2, AlertCircle, Download, FileText, Plus } from "lucide-react";
|
||||
import { Loader2, AlertCircle, Download, FileText, Plus, ExternalLink, BookOpen } from "lucide-react";
|
||||
import {
|
||||
getComplianceFrameworks,
|
||||
getFrameworkStatus,
|
||||
@@ -47,6 +47,7 @@ export default function CompliancePage() {
|
||||
const isLoading = loadingFrameworks || loadingStatus;
|
||||
const summary = frameworkStatus?.summary;
|
||||
const controls = frameworkStatus?.controls || [];
|
||||
const activeFramework = frameworks?.find((f) => f.id === activeFrameworkId) ?? null;
|
||||
|
||||
const handleExportCSV = async () => {
|
||||
if (activeFrameworkId) {
|
||||
@@ -166,6 +167,36 @@ export default function CompliancePage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Framework info banner */}
|
||||
{activeFramework?.description && (
|
||||
<div className="flex items-start gap-3 rounded-xl border border-gray-700/60 bg-gray-900/60 px-5 py-4">
|
||||
<BookOpen className="mt-0.5 h-4 w-4 shrink-0 text-cyan-400" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex flex-wrap items-center gap-2 mb-1">
|
||||
<span className="text-sm font-semibold text-white">{activeFramework.name}</span>
|
||||
{activeFramework.version && (
|
||||
<span className="rounded-full border border-gray-700 bg-gray-800 px-2 py-0.5 text-[10px] text-gray-400">
|
||||
v{activeFramework.version}
|
||||
</span>
|
||||
)}
|
||||
{activeFramework.url && (
|
||||
<a
|
||||
href={activeFramework.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-1 text-[10px] text-cyan-400 hover:text-cyan-300 transition-colors"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<ExternalLink className="h-3 w-3" />
|
||||
Official standard
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs leading-relaxed text-gray-400">{activeFramework.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Summary cards */}
|
||||
{summary && (
|
||||
<div className="grid grid-cols-2 gap-4 lg:grid-cols-5">
|
||||
|
||||
Reference in New Issue
Block a user