'use client' /** * Source Policy Management Page (SDK Version) * * Whitelist-based data source management for compliance RAG corpus. * Controls which legal sources may be used, PII rules, and audit trail. */ import { useState, useEffect } from 'react' import { useSDK } from '@/lib/sdk' import StepHeader from '@/components/sdk/StepHeader/StepHeader' import { SourcesTab } from '@/components/sdk/source-policy/SourcesTab' import { OperationsMatrixTab } from '@/components/sdk/source-policy/OperationsMatrixTab' import { PIIRulesTab } from '@/components/sdk/source-policy/PIIRulesTab' import { AuditTab } from '@/components/sdk/source-policy/AuditTab' // API base URL — now uses Next.js proxy routes const API_BASE = '/api/sdk/v1/source-policy' interface PolicyStats { active_policies: number allowed_sources: number pii_rules: number blocked_today: number blocked_total: number } type TabId = 'dashboard' | 'sources' | 'operations' | 'pii' | 'audit' export default function SourcePolicyPage() { const { state } = useSDK() const [activeTab, setActiveTab] = useState('dashboard') const [stats, setStats] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) useEffect(() => { fetchStats() }, []) const fetchStats = async () => { try { setLoading(true) const res = await fetch(`${API_BASE}/policy-stats`) if (!res.ok) { throw new Error('Fehler beim Laden der Statistiken') } const data = await res.json() setStats(data) } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') setStats({ active_policies: 0, allowed_sources: 0, pii_rules: 0, blocked_today: 0, blocked_total: 0, }) } finally { setLoading(false) } } const tabs: { id: TabId; name: string; icon: JSX.Element }[] = [ { id: 'dashboard', name: 'Dashboard', icon: ( ), }, { id: 'sources', name: 'Quellen', icon: ( ), }, { id: 'operations', name: 'Operations', icon: ( ), }, { id: 'pii', name: 'PII-Regeln', icon: ( ), }, { id: 'audit', name: 'Audit', icon: ( ), }, ] return (
{/* Error Display */} {error && (
{error}
)} {/* Stats Cards */} {stats && (
{stats.active_policies}
Aktive Policies
{stats.allowed_sources}
Zugelassene Quellen
{stats.blocked_today}
Blockiert (heute)
{stats.pii_rules}
PII-Regeln
)} {/* Tabs */}
{tabs.map((tab) => ( ))}
{/* Tab Content */} <> {activeTab === 'dashboard' && stats && (

Quellen-Uebersicht

Zugelassene Quellen {stats.allowed_sources}
Aktive Policies {stats.active_policies}
0 ? Math.min((stats.active_policies / stats.allowed_sources) * 100, 100) : 0}%` }} />

Datenschutz-Regeln

PII-Regeln aktiv {stats.pii_rules}
Blockiert (heute) 0 ? 'text-red-600' : 'text-green-600'}`}> {stats.blocked_today}
Blockiert (gesamt) {stats.blocked_total}

Compliance-Status

Quellen konfiguriert
{stats.allowed_sources > 0 ? 'Ja' : 'Nein'}
PII-Schutz aktiv
{stats.pii_rules > 0 ? 'Ja' : 'Nein'}
Policies definiert
{stats.active_policies > 0 ? 'Ja' : 'Nein'}
)} {activeTab === 'dashboard' && !stats && loading && (
Lade Dashboard...
)} {activeTab === 'sources' && } {activeTab === 'operations' && } {activeTab === 'pii' && } {activeTab === 'audit' && }
) }