Implement full evidence integrity pipeline to prevent compliance theater: - Confidence levels (E0-E4), truth status tracking, assertion engine - Four-Eyes approval workflow, audit trail, reject endpoint - Evidence distribution dashboard, LLM audit routes - Traceability matrix (backend endpoint + Compliance Hub UI tab) - Anti-fake badges, control status machine, normative patterns - 2 migrations, 4 test suites, MkDocs documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
112 lines
3.9 KiB
TypeScript
112 lines
3.9 KiB
TypeScript
"use client"
|
||
|
||
import React from "react"
|
||
|
||
const badgeBase = "inline-flex items-center px-2 py-0.5 rounded text-xs font-medium"
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Confidence Level Badge (E0–E4)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const confidenceColors: Record<string, string> = {
|
||
E0: "bg-red-100 text-red-800",
|
||
E1: "bg-yellow-100 text-yellow-800",
|
||
E2: "bg-blue-100 text-blue-800",
|
||
E3: "bg-green-100 text-green-800",
|
||
E4: "bg-emerald-100 text-emerald-800",
|
||
}
|
||
|
||
const confidenceLabels: Record<string, string> = {
|
||
E0: "E0 — Generiert",
|
||
E1: "E1 — Manuell",
|
||
E2: "E2 — Intern validiert",
|
||
E3: "E3 — System-beobachtet",
|
||
E4: "E4 — Extern auditiert",
|
||
}
|
||
|
||
export function ConfidenceLevelBadge({ level }: { level?: string | null }) {
|
||
if (!level) return null
|
||
const color = confidenceColors[level] || "bg-gray-100 text-gray-800"
|
||
const label = confidenceLabels[level] || level
|
||
return <span className={`${badgeBase} ${color}`}>{label}</span>
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Truth Status Badge
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const truthColors: Record<string, string> = {
|
||
generated: "bg-violet-100 text-violet-800",
|
||
uploaded: "bg-gray-100 text-gray-800",
|
||
observed: "bg-blue-100 text-blue-800",
|
||
validated: "bg-green-100 text-green-800",
|
||
rejected: "bg-red-100 text-red-800",
|
||
audited: "bg-emerald-100 text-emerald-800",
|
||
}
|
||
|
||
const truthLabels: Record<string, string> = {
|
||
generated: "Generiert",
|
||
uploaded: "Hochgeladen",
|
||
observed: "Beobachtet",
|
||
validated: "Validiert",
|
||
rejected: "Abgelehnt",
|
||
audited: "Auditiert",
|
||
}
|
||
|
||
export function TruthStatusBadge({ status }: { status?: string | null }) {
|
||
if (!status) return null
|
||
const color = truthColors[status] || "bg-gray-100 text-gray-800"
|
||
const label = truthLabels[status] || status
|
||
return <span className={`${badgeBase} ${color}`}>{label}</span>
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Generation Mode Badge (sparkles icon)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
export function GenerationModeBadge({ mode }: { mode?: string | null }) {
|
||
if (!mode) return null
|
||
return (
|
||
<span className={`${badgeBase} bg-violet-100 text-violet-800`}>
|
||
<svg className="w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20">
|
||
<path d="M5 2a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0V6H3a1 1 0 010-2h1V3a1 1 0 011-1zm0 10a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0v-1H3a1 1 0 010-2h1v-1a1 1 0 011-1zm7-10a1 1 0 01.967.744L14.146 7.2 17.5 7.512a1 1 0 010 1.976l-3.354.313-1.18 4.456a1 1 0 01-1.932 0l-1.18-4.456-3.354-.313a1 1 0 010-1.976l3.354-.313 1.18-4.456A1 1 0 0112 2z" />
|
||
</svg>
|
||
KI-generiert
|
||
</span>
|
||
)
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Approval Status Badge (Four-Eyes)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
const approvalColors: Record<string, string> = {
|
||
none: "bg-gray-100 text-gray-600",
|
||
pending_first: "bg-yellow-100 text-yellow-800",
|
||
first_approved: "bg-blue-100 text-blue-800",
|
||
approved: "bg-green-100 text-green-800",
|
||
rejected: "bg-red-100 text-red-800",
|
||
}
|
||
|
||
const approvalLabels: Record<string, string> = {
|
||
none: "Kein Review",
|
||
pending_first: "Warte auf 1. Review",
|
||
first_approved: "1. Review OK",
|
||
approved: "Genehmigt (4-Augen)",
|
||
rejected: "Abgelehnt",
|
||
}
|
||
|
||
export function ApprovalStatusBadge({
|
||
status,
|
||
requiresFourEyes,
|
||
}: {
|
||
status?: string | null
|
||
requiresFourEyes?: boolean | null
|
||
}) {
|
||
if (!requiresFourEyes) return null
|
||
const s = status || "none"
|
||
const color = approvalColors[s] || "bg-gray-100 text-gray-600"
|
||
const label = approvalLabels[s] || s
|
||
return <span className={`${badgeBase} ${color}`}>{label}</span>
|
||
}
|