add non compliance

This commit is contained in:
Ishaan Jaffer 2026-02-17 18:49:02 -08:00
parent 5946a933a0
commit c4c2b8cb68
2 changed files with 118 additions and 42 deletions

View file

@ -1,10 +1,7 @@
import React, { useState, useEffect } from "react";
import React, { useState, useMemo } from "react";
import { Tooltip } from "antd";
import {
checkEuAiActCompliance,
checkGdprCompliance,
ComplianceResponse,
ComplianceCheckRequest,
} from "@/components/networking";
interface CompliancePanelProps {
@ -18,6 +15,102 @@ interface CompliancePanelProps {
};
}
function runComplianceChecksLocally(logEntry: CompliancePanelProps["logEntry"]): {
euAiAct: ComplianceResponse;
gdpr: ComplianceResponse;
} {
const guardrails: Record<string, any>[] = logEntry.metadata?.guardrail_information ?? [];
const hasGuardrails = guardrails.length > 0;
const preCallGuardrails = guardrails.filter(
(g) => g.guardrail_mode === "pre_call" || !g.guardrail_mode
);
const hasPreCall = preCallGuardrails.length > 0;
const hasUser = Boolean(logEntry.user);
const hasModel = Boolean(logEntry.model);
const hasTimestamp = Boolean(logEntry.startTime);
const auditComplete = hasUser && hasModel && hasTimestamp && hasGuardrails;
const missingFields: string[] = [];
if (!hasUser) missingFields.push("user_id");
if (!hasModel) missingFields.push("model");
if (!hasTimestamp) missingFields.push("timestamp");
if (!hasGuardrails) missingFields.push("guardrail_results");
const hasIntervention = preCallGuardrails.some((g) =>
["guardrail_intervened", "failed", "blocked"].includes(g.guardrail_status ?? "")
);
const allPassed =
preCallGuardrails.length > 0 &&
preCallGuardrails.every((g) => g.guardrail_status === "success");
const dataProtected = hasIntervention || allPassed;
const euAiAct: ComplianceResponse = {
regulation: "EU AI Act",
compliant: hasGuardrails && hasPreCall && auditComplete,
checks: [
{
check_name: "Guardrails applied",
article: "Art. 9",
passed: hasGuardrails,
detail: hasGuardrails
? `${guardrails.length} guardrail(s) applied`
: "No guardrails applied",
},
{
check_name: "Content screened before LLM",
article: "Art. 5",
passed: hasPreCall,
detail: hasPreCall
? `${preCallGuardrails.length} pre-call guardrail(s) screened content`
: "No pre-call screening applied",
},
{
check_name: "Audit record complete",
article: "Art. 12",
passed: auditComplete,
detail: auditComplete
? "All required audit fields present"
: `Missing: ${missingFields.join(", ")}`,
},
],
};
const gdpr: ComplianceResponse = {
regulation: "GDPR",
compliant: hasPreCall && dataProtected && auditComplete,
checks: [
{
check_name: "Data protection applied",
article: "Art. 32",
passed: hasPreCall,
detail: hasPreCall
? `${preCallGuardrails.length} pre-call guardrail(s) protect data`
: "No pre-call data protection applied",
},
{
check_name: "Sensitive data protected",
article: "Art. 5(1)(c)",
passed: dataProtected,
detail: hasIntervention
? "Guardrail intervened to protect sensitive data"
: allPassed
? "No sensitive data detected"
: "No pre-call guardrails to protect sensitive data",
},
{
check_name: "Audit record complete",
article: "Art. 30",
passed: auditComplete,
detail: auditComplete
? "All required audit fields present"
: `Missing: ${missingFields.join(", ")}`,
},
],
};
return { euAiAct, gdpr };
}
// -- Icons --
const CheckIcon = () => (
@ -136,38 +229,7 @@ const ComplianceCard = ({
// -- Main Component --
const CompliancePanel: React.FC<CompliancePanelProps> = ({ accessToken, logEntry }) => {
const [euAiActData, setEuAiActData] = useState<ComplianceResponse | null>(null);
const [gdprData, setGdprData] = useState<ComplianceResponse | null>(null);
const [euAiActLoading, setEuAiActLoading] = useState(false);
const [gdprLoading, setGdprLoading] = useState(false);
const [euAiActError, setEuAiActError] = useState<string | null>(null);
const [gdprError, setGdprError] = useState<string | null>(null);
useEffect(() => {
if (!accessToken || !logEntry.request_id) return;
const payload: ComplianceCheckRequest = {
request_id: logEntry.request_id,
user_id: logEntry.user,
model: logEntry.model,
timestamp: logEntry.startTime,
guardrail_information: logEntry.metadata?.guardrail_information,
};
setEuAiActLoading(true);
setEuAiActError(null);
checkEuAiActCompliance(accessToken, payload)
.then(setEuAiActData)
.catch((err) => setEuAiActError(err.message || "Failed to check EU AI Act compliance"))
.finally(() => setEuAiActLoading(false));
setGdprLoading(true);
setGdprError(null);
checkGdprCompliance(accessToken, payload)
.then(setGdprData)
.catch((err) => setGdprError(err.message || "Failed to check GDPR compliance"))
.finally(() => setGdprLoading(false));
}, [accessToken, logEntry]);
const { euAiAct, gdpr } = useMemo(() => runComplianceChecksLocally(logEntry), [logEntry]);
return (
<div>
@ -177,15 +239,15 @@ const CompliancePanel: React.FC<CompliancePanelProps> = ({ accessToken, logEntry
<div className="space-y-3">
<ComplianceCard
title="EU AI Act"
data={euAiActData}
loading={euAiActLoading}
error={euAiActError}
data={euAiAct}
loading={false}
error={null}
/>
<ComplianceCard
title="GDPR"
data={gdprData}
loading={gdprLoading}
error={gdprError}
data={gdpr}
loading={false}
error={null}
/>
</div>
</div>

View file

@ -165,6 +165,20 @@ export function LogDetailContent({ logEntry, onOpenSettings, isLoadingDetails =
/>
)}
{/* Compliance Panel always visible */}
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden mb-6 p-4">
<CompliancePanel
accessToken={accessToken ?? null}
logEntry={{
request_id: logEntry.request_id,
user: logEntry.user,
model: logEntry.model,
startTime: logEntry.startTime,
metadata: logEntry.metadata,
}}
/>
</div>
{/* Guardrail Data */}
{hasGuardrailData && (
<div id="guardrail-section">