'use client' import { useState, useEffect } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { Language } from '@/lib/types' import { t } from '@/lib/i18n' import GradientText from '../ui/GradientText' import FadeInView from '../ui/FadeInView' import { Brain, Shield, ScanLine, Zap, Cpu, Layers, Wrench, X, Users, Lock, Server, Network, ChevronRight, BadgeCheck, } from 'lucide-react' interface ArchitectureSlideProps { lang: Language } type NodeId = 'certifai' | 'complai' | 'scanner' | 'litellm' | 'llm' | 'embeddings' | 'tools' type ConnType = 'api' | 'mcp' | 'embed' | 'tool' interface NodeDef { id: NodeId icon: React.ElementType title: string subtitle: string color: string twColor: string twBorder: string twBg: string twDot: string cx: number cy: number tier: 'product' | 'proxy' | 'inference' tech: string[] services: { name: string; desc: string }[] badge?: string } interface ConnDef { from: NodeId to: NodeId type: ConnType d: string revD?: string // reverse path for bidirectional MCP } const CONNS: ConnDef[] = [ { from: 'certifai', to: 'litellm', type: 'api', d: 'M 18 22 Q 28 43 50 52' }, { from: 'complai', to: 'litellm', type: 'api', d: 'M 50 22 L 50 52' }, { from: 'scanner', to: 'litellm', type: 'api', d: 'M 82 22 Q 72 43 50 52' }, { from: 'complai', to: 'scanner', type: 'mcp', d: 'M 50 22 Q 66 9 82 22', revD: 'M 82 22 Q 66 9 50 22' }, { from: 'litellm', to: 'llm', type: 'api', d: 'M 50 52 Q 37 67 18 82' }, { from: 'litellm', to: 'embeddings', type: 'embed', d: 'M 50 52 L 50 82' }, { from: 'litellm', to: 'tools', type: 'tool', d: 'M 50 52 Q 63 67 82 82' }, ] function getNodes(de: boolean): NodeDef[] { return [ { id: 'certifai', icon: Brain, title: 'CERTifAI', subtitle: de ? 'GenAI Mandantenportal' : 'GenAI Tenant Portal', color: '#c084fc', twColor: 'text-purple-400', twBorder: 'border-purple-500/50', twBg: 'bg-purple-500/10', twDot: 'bg-purple-400', cx: 18, cy: 22, tier: 'product', badge: 'Rust · Dioxus', tech: ['Rust', 'Dioxus', 'MongoDB', 'Keycloak', 'SearXNG', 'LangGraph'], services: [ { name: 'LiteLLM Dashboard', desc: de ? 'Modellverwaltung & Kostentracking' : 'Model mgmt & cost tracking' }, { name: 'LibreChat + SSO', desc: de ? 'Mandanten-Chat mit Keycloak' : 'Tenant chat with Keycloak' }, { name: 'LangGraph Agents', desc: de ? 'Agent-Orchestrierung' : 'Agent orchestration' }, { name: 'MCP Hub', desc: de ? 'Tool-Integration für KI-Clients' : 'Tool integration for AI clients' }, ], }, { id: 'complai', icon: Shield, title: 'COMPLAI', subtitle: de ? 'Compliance & Audit' : 'Compliance & Audit', color: '#818cf8', twColor: 'text-indigo-400', twBorder: 'border-indigo-500/50', twBg: 'bg-indigo-500/10', twDot: 'bg-indigo-400', cx: 50, cy: 22, tier: 'product', badge: 'Next.js · FastAPI', tech: ['Next.js 15', 'FastAPI', 'Go/Gin', 'PostgreSQL', 'Qdrant', 'Valkey'], services: [ { name: de ? 'DSGVO / AI Act / NIS2' : 'GDPR / AI Act / NIS2', desc: de ? '70k+ auditierbare Controls' : '70k+ auditable controls' }, { name: 'RAG Pipeline', desc: de ? '75+ Rechtsquellen, semantische Suche' : '75+ legal sources, semantic search' }, { name: 'Control Pipeline', desc: de ? 'Gesetzestextanalyse via LLM' : 'Legal text analysis via LLM' }, { name: 'MCP Client', desc: de ? 'Echtzeit-Findings vom Scanner' : 'Real-time findings from Scanner' }, ], }, { id: 'scanner', icon: ScanLine, title: 'Compliance Scanner', subtitle: de ? 'Code-Sicherheit' : 'Code Security', color: '#34d399', twColor: 'text-emerald-400', twBorder: 'border-emerald-500/50', twBg: 'bg-emerald-500/10', twDot: 'bg-emerald-400', cx: 82, cy: 22, tier: 'product', badge: 'Rust · Axum', tech: ['Rust', 'Axum', 'MongoDB', 'Semgrep', 'Gitleaks', 'Syft'], services: [ { name: 'SAST / SBOM / CVE', desc: de ? 'Vollautomatische Pipeline' : 'Fully automated pipeline' }, { name: de ? 'KI-Triage' : 'AI Triage', desc: de ? 'LLM filtert False Positives' : 'LLM filters false positives' }, { name: de ? 'KI-Pentest' : 'AI Pentest', desc: de ? 'Autonome Angriffsketten' : 'Autonomous attack chains' }, { name: 'MCP Server', desc: de ? 'Live-Findings für COMPLAI' : 'Live findings for COMPLAI' }, ], }, { id: 'litellm', icon: Zap, title: 'LiteLLM Proxy', subtitle: de ? 'KI-Gateway & Guardrails' : 'AI Gateway & Guardrails', color: '#fbbf24', twColor: 'text-amber-400', twBorder: 'border-amber-500/60', twBg: 'bg-amber-500/10', twDot: 'bg-amber-400', cx: 50, cy: 52, tier: 'proxy', badge: 'Hub', tech: ['OpenAI-kompatible API', 'Bearer Auth', 'Rate Limiting', 'PII-Filter', 'Spend Tracking'], services: [ { name: de ? 'Token-Budget' : 'Token Budget', desc: de ? 'Pro-Mandant Kontingente & Abrechnung' : 'Per-tenant quotas & billing' }, { name: 'PII Guardrails', desc: de ? 'Datenschutz-Filter für alle Anfragen' : 'Privacy filter on all requests' }, { name: de ? 'Web-Suche (anonym)' : 'Web Search (anon)', desc: de ? 'SearXNG-Proxy, kein US-Anbieter' : 'SearXNG proxy, no US providers' }, { name: de ? 'Namespace-Isolierung' : 'Namespace Isolation', desc: de ? 'Mandantentrennung per API-Key' : 'Tenant isolation per API key' }, { name: de ? 'Failover-Routing' : 'Failover Routing', desc: de ? 'Automatisches Fallback' : 'Automatic fallback between models' }, ], }, { id: 'llm', icon: Cpu, title: de ? 'LLM Inferenz' : 'LLM Inference', subtitle: de ? 'Lokale Sprachmodelle' : 'Local Language Models', color: '#60a5fa', twColor: 'text-blue-400', twBorder: 'border-blue-500/50', twBg: 'bg-blue-500/10', twDot: 'bg-blue-400', cx: 18, cy: 82, tier: 'inference', badge: de ? 'On-Premise · BSI' : 'On-Premise · BSI', tech: ['Qwen3-32B', 'Qwen3-Coder-30B', 'DeepSeek-R1-8B', 'Ollama'], services: [ { name: de ? 'Vollständig lokal' : 'Fully local', desc: de ? 'Daten verlassen nie den Server' : 'Data never leaves the server' }, { name: de ? 'Air-Gap fähig' : 'Air-Gap Capable', desc: de ? 'Kein Internet erforderlich' : 'No internet required' }, { name: de ? 'GPU-optimiert' : 'GPU-optimized', desc: de ? 'Dedizierte Inferenz-Hardware' : 'Dedicated inference hardware' }, ], }, { id: 'embeddings', icon: Layers, title: 'Embeddings', subtitle: de ? 'Semantische Suche' : 'Semantic Search', color: '#a78bfa', twColor: 'text-violet-400', twBorder: 'border-violet-500/50', twBg: 'bg-violet-500/10', twDot: 'bg-violet-400', cx: 50, cy: 82, tier: 'inference', badge: de ? 'EU-Souverän' : 'EU Sovereign', tech: ['bge-m3', 'Qdrant Vector DB', 'Sentence-Transformers'], services: [ { name: 'RAG Pipeline', desc: de ? '75+ Rechtsquellen indexiert' : '75+ legal sources indexed' }, { name: de ? 'Semantische Suche' : 'Semantic Search', desc: de ? 'Multi-linguale Einbettungen' : 'Multi-lingual embeddings' }, { name: de ? 'Lokal' : 'Fully local', desc: de ? 'Keine externen APIs' : 'No external APIs' }, ], }, { id: 'tools', icon: Wrench, title: de ? 'KI-Tools' : 'AI Tools', subtitle: de ? 'Web-Suche & MCP' : 'Web Search & MCP', color: '#2dd4bf', twColor: 'text-teal-400', twBorder: 'border-teal-500/50', twBg: 'bg-teal-500/10', twDot: 'bg-teal-400', cx: 82, cy: 82, tier: 'inference', badge: de ? 'EU-Souverän' : 'EU Sovereign', tech: ['SearXNG', 'MCP Protocol', 'Semgrep API', 'Gitleaks API'], services: [ { name: 'SearXNG', desc: de ? 'Anonymisierte EU-Websuche' : 'Anonymized EU web search' }, { name: 'MCP Tools', desc: de ? 'Auditdokumente & Code-Findings' : 'Audit docs & code findings' }, { name: de ? 'Kein US-Anbieter' : 'No US providers', desc: de ? '100% DSGVO-konform' : '100% GDPR-compliant' }, ], }, ] } // ── Token counter (inference tier ambient animation) ───────────────────────── function TokenTicker({ color }: { color: string }) { const [n, setN] = useState(() => 12480 + Math.floor(Math.random() * 8000)) useEffect(() => { const id = setInterval(() => setN(v => v + Math.floor(Math.random() * 180 + 40)), 220) return () => clearInterval(id) }, []) return (
{n.toLocaleString('de-DE')} tok/s
) } // ── Data-flow path (always-on packets, fast when active) ───────────────────── function DataFlow({ d, revD, color, active, type, }: { d: string; revD?: string; color: string; active: boolean; type: ConnType }) { const isMcp = type === 'mcp' const speed = active ? 1.2 : 5 const op = active ? 0.85 : 0.2 const w = active ? 2.5 : 1.2 const dash = active ? 3 : 2 return ( {/* Base line */} {/* Forward packets */} {[0, -28, -56].map((off, i) => ( ))} {/* Reverse packets for MCP (bidirectional) */} {isMcp && revD && [0, -42].map((off, i) => ( ))} ) } // ── Node card ────────────────────────────────────────────────────────────────── // Position wrapper (div) is never scaled — only the inner motion.button scales. // This prevents the "snap" that happened when translate(-50%,-50%) and scale // were on the same element. function NodeCard({ node, active, onClick, de, }: { node: NodeDef; active: boolean; onClick: () => void; de: boolean }) { const Icon = node.icon const isHub = node.id === 'litellm' return (
{/* Left accent bar */}
{/* Icon + title */}
{node.title} {active && (
)}
{/* Subtitle */}

{node.subtitle}

{/* Badge */} {node.badge && (
{node.badge}
)} {/* Token ticker on inference nodes */} {active && node.tier === 'inference' && (
)} {/* Hub: spinning indicator ring */} {isHub && active && ( )}
) } // ── Main slide ───────────────────────────────────────────────────────────────── export default function ArchitectureSlide({ lang }: ArchitectureSlideProps) { const i = t(lang) const de = lang === 'de' const nodes = getNodes(de) const [activeId, setActiveId] = useState(null) const active = nodes.find(n => n.id === activeId) ?? null function toggle(id: NodeId) { setActiveId(prev => (prev === id ? null : id)) } const tenants = de ? ['Mandant A', 'Mandant B', 'Mandant C', 'Mandant N…'] : ['Namespace A', 'Namespace B', 'Namespace C', 'Namespace N…'] const tiers = [ { y: '22%', label: de ? 'Anwendungsschicht' : 'Application Layer', clr: '#818cf8', badge: null }, { y: '52%', label: de ? 'GenAI-Infrastruktur' : 'GenAI Infrastructure', clr: '#fbbf24', badge: de ? 'BSI-Rechenzentrum' : 'BSI Data Center' }, { y: '82%', label: de ? 'Inferenzschicht' : 'Inference Layer', clr: '#60a5fa', badge: de ? 'BSI · EU-Souverän' : 'BSI · EU Sovereign' }, ] return (
{/* Header */}

{de ? 'Anhang' : 'Appendix'}

{i.annex.architecture.title}

{de ? 'Klicke auf eine Komponente für Details' : 'Click any component to explore'}

{/* Customer namespace strip */}
{de ? 'Kundenmandanten' : 'Customer Namespaces'} {tenants.map(tn => ( {tn} ))}
{/* ── MAP ──────────────────────────────────────────────────────────── */}
{/* Background */}
{/* Tier separator lines */} {['37%', '66%'].map(y => (
))} {/* Tier labels (left) + BSI badges (right) */} {tiers.map(({ y, label, clr, badge }) => (
{label}
{badge && (
{badge}
)}
))} {/* MCP badge between COMPLAI and Scanner */}
MCP ↔
{/* Infra tech chips (secondary, very subtle, in the infra tier band) */}
{['PostgreSQL', 'MongoDB', 'Qdrant', 'Valkey', 'Nginx', 'Vault', 'Gitea', 'Orca', 'Woodpecker'].map(chip => ( {chip} ))}
{/* SVG: island territories + data-flow paths */} {/* Tier zone fills */} {/* Island blobs per node */} {nodes.map(n => { const isHub = n.id === 'litellm' const isActive = activeId === n.id return ( ) })} {/* Connection flows */} {CONNS.map(c => { const fromNode = nodes.find(n => n.id === c.from)! const toNode = nodes.find(n => n.id === c.to)! const isActive = activeId === c.from || activeId === c.to const color = isActive ? (activeId === c.from ? fromNode.color : toNode.color) : '#ffffff' return ( ) })} {/* Node cards */} {nodes.map(node => ( toggle(node.id)} de={de} /> ))} {!activeId && (
{de ? 'Komponente anklicken' : 'Click any node'}
)}
{/* ── DETAIL PANEL ──────────────────────────────────────────────────── */} {active && ( {/* Header */}

{active.title}

{active.badge && ( {active.badge} )} {active.tier === 'product' ? (de ? 'Anwendungsschicht' : 'Application Layer') : active.tier === 'proxy' ? (de ? 'GenAI-Infrastruktur' : 'GenAI Infra') : (de ? 'Inferenzschicht' : 'Inference Layer')}

{active.subtitle}

{/* Body */}

{de ? 'Stack' : 'Tech Stack'}

{active.tech.map(tk => ( {tk} ))}

{de ? 'Funktionen' : 'Capabilities'}

{active.services.map(s => (
{s.name} {s.desc}
))}
{/* Connects-to */}
{de ? 'Verbunden mit:' : 'Connects to:'} {CONNS .filter(c => c.from === active.id || c.to === active.id) .map(c => { const peerId = c.from === active.id ? c.to : c.from const peer = nodes.find(n => n.id === peerId)! const label = c.type === 'mcp' ? 'MCP' : c.type === 'embed' ? 'Embed' : c.type === 'tool' ? 'Tool' : 'API' return ( ) })}
)} {/* Bottom legend */} {!active && ( {[ { icon: Lock, text: de ? 'Kein US-Anbieter · 100% DSGVO' : 'No US providers · 100% GDPR' }, { icon: Server, text: de ? 'BSI-zertifiziertes Rechenzentrum' : 'BSI-certified data center' }, { icon: BadgeCheck, text: de ? 'EU-souveräne Inferenz' : 'EU-sovereign inference' }, ].map(({ icon: Icon, text }) => ( {text} ))} )}
) }