feat: 7 Vorbereitungs-Module auf 100% — Frontend, Proxy-Routen, Backend-Fixes
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 35s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 19s

Profil: machineBuilder-Felder im POST-Body, PATCH-Handler
Scope: API-Route (GET/POST), ScopeDecisionTab Props + Buttons, Export-Druckansicht HTML
Anwendung: PUT-Handler, Bearbeiten-Button, Pagination/Search
Import: Verlauf laden, DELETE-Route, Offline-Badge, ObjectURL Memory-Leak fix
Screening: Security-Backlog Button verdrahtet, Scan-Verlauf
Module: Detail-Seite, GET-Proxy, Konfigurieren-Button, Modul-erstellen-Modal, Error-Toast
Quellen: 10 Proxy-Routen, Tab-Komponenten umgestellt, Dashboard-Tab, blocked_today Bug fix, Datum-Filter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-02 15:08:13 +01:00
parent fc83ebfd82
commit d079886819
32 changed files with 1734 additions and 76 deletions

View File

@@ -15,15 +15,8 @@ import { OperationsMatrixTab } from '@/components/sdk/source-policy/OperationsMa
import { PIIRulesTab } from '@/components/sdk/source-policy/PIIRulesTab'
import { AuditTab } from '@/components/sdk/source-policy/AuditTab'
// API base URL for backend-compliance
const getApiBase = () => {
if (typeof window === 'undefined') return 'http://localhost:8002/api'
const hostname = window.location.hostname
if (hostname === 'localhost' || hostname === '127.0.0.1') {
return 'http://localhost:8002/api'
}
return `https://${hostname}:8002/api`
}
// API base URL — now uses Next.js proxy routes
const API_BASE = '/api/sdk/v1/source-policy'
interface PolicyStats {
active_policies: number
@@ -41,23 +34,15 @@ export default function SourcePolicyPage() {
const [stats, setStats] = useState<PolicyStats | null>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const [apiBase, setApiBase] = useState<string | null>(null)
useEffect(() => {
const base = getApiBase()
setApiBase(base)
fetchStats()
}, [])
useEffect(() => {
if (apiBase !== null) {
fetchStats()
}
}, [apiBase])
const fetchStats = async () => {
try {
setLoading(true)
const res = await fetch(`${apiBase}/v1/admin/policy-stats`)
const res = await fetch(`${API_BASE}/policy-stats`)
if (!res.ok) {
throw new Error('Fehler beim Laden der Statistiken')
@@ -182,21 +167,82 @@ export default function SourcePolicyPage() {
</div>
{/* Tab Content */}
{apiBase === null ? (
<div className="text-center py-12 text-slate-500">Initialisiere...</div>
) : (
<>
{activeTab === 'dashboard' && (
<div className="text-center py-12 text-slate-500">
{loading ? 'Lade Dashboard...' : 'Dashboard-Ansicht - Wechseln Sie zu einem Tab fuer Details.'}
<>
{activeTab === 'dashboard' && stats && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="bg-white rounded-xl border border-gray-200 p-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Quellen-Uebersicht</h3>
<div className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Zugelassene Quellen</span>
<span className="text-2xl font-bold text-green-600">{stats.allowed_sources}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Aktive Policies</span>
<span className="text-2xl font-bold text-purple-600">{stats.active_policies}</span>
</div>
<div className="h-2 bg-gray-100 rounded-full overflow-hidden">
<div
className="h-full bg-green-500 rounded-full"
style={{ width: `${stats.allowed_sources > 0 ? Math.min((stats.active_policies / stats.allowed_sources) * 100, 100) : 0}%` }}
/>
</div>
</div>
</div>
)}
{activeTab === 'sources' && <SourcesTab apiBase={apiBase} onUpdate={fetchStats} />}
{activeTab === 'operations' && <OperationsMatrixTab apiBase={apiBase} />}
{activeTab === 'pii' && <PIIRulesTab apiBase={apiBase} onUpdate={fetchStats} />}
{activeTab === 'audit' && <AuditTab apiBase={apiBase} />}
</>
)}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Datenschutz-Regeln</h3>
<div className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">PII-Regeln aktiv</span>
<span className="text-2xl font-bold text-blue-600">{stats.pii_rules}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Blockiert (heute)</span>
<span className={`text-2xl font-bold ${stats.blocked_today > 0 ? 'text-red-600' : 'text-green-600'}`}>
{stats.blocked_today}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Blockiert (gesamt)</span>
<span className="text-lg font-semibold text-gray-500">{stats.blocked_total}</span>
</div>
</div>
</div>
<div className="md:col-span-2 bg-white rounded-xl border border-gray-200 p-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Compliance-Status</h3>
<div className="flex items-center gap-6">
<div className="flex-1 text-center p-4 bg-green-50 rounded-lg">
<div className="text-sm text-green-700 font-medium">Quellen konfiguriert</div>
<div className="text-3xl font-bold text-green-600 mt-1">
{stats.allowed_sources > 0 ? 'Ja' : 'Nein'}
</div>
</div>
<div className="flex-1 text-center p-4 bg-blue-50 rounded-lg">
<div className="text-sm text-blue-700 font-medium">PII-Schutz aktiv</div>
<div className="text-3xl font-bold text-blue-600 mt-1">
{stats.pii_rules > 0 ? 'Ja' : 'Nein'}
</div>
</div>
<div className="flex-1 text-center p-4 bg-purple-50 rounded-lg">
<div className="text-sm text-purple-700 font-medium">Policies definiert</div>
<div className="text-3xl font-bold text-purple-600 mt-1">
{stats.active_policies > 0 ? 'Ja' : 'Nein'}
</div>
</div>
</div>
</div>
</div>
)}
{activeTab === 'dashboard' && !stats && loading && (
<div className="text-center py-12 text-slate-500">Lade Dashboard...</div>
)}
{activeTab === 'sources' && <SourcesTab apiBase={API_BASE} onUpdate={fetchStats} />}
{activeTab === 'operations' && <OperationsMatrixTab apiBase={API_BASE} />}
{activeTab === 'pii' && <PIIRulesTab apiBase={API_BASE} onUpdate={fetchStats} />}
{activeTab === 'audit' && <AuditTab apiBase={API_BASE} />}
</>
</div>
)
}