feat: ZeroClaw compliance agent — document analysis + role assignment + email
Add autonomous compliance agent that fetches web documents (cookie banners, privacy policies), classifies them via Qwen/Ollama, assesses DSGVO compliance, assigns to the responsible role, and sends notification emails. Components: - ZeroClaw SOP (6-step workflow: fetch, classify, assess, summarize, assign, notify) - Backend: /api/compliance/agent/analyze (combined endpoint) - Backend: /api/compliance/agent/notify (standalone email) - Frontend: /sdk/agent page (Manager UI with URL input + results) - Helper scripts + E2E test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
80
admin-compliance/app/sdk/agent/_hooks/useAgentAnalysis.ts
Normal file
80
admin-compliance/app/sdk/agent/_hooks/useAgentAnalysis.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
|
||||
export interface AnalysisResult {
|
||||
url: string
|
||||
classification: string
|
||||
risk_level: string
|
||||
risk_score: number
|
||||
escalation_level: string
|
||||
responsible_role: string
|
||||
findings: string[]
|
||||
required_controls: string[]
|
||||
summary: string
|
||||
email_status: string
|
||||
analyzed_at: string
|
||||
}
|
||||
|
||||
const ESCALATION_ROLES: Record<string, string> = {
|
||||
E0: 'Kein Handlungsbedarf',
|
||||
E1: 'Teamleitung Datenschutz',
|
||||
E2: 'Datenschutzbeauftragter (DSB)',
|
||||
E3: 'DSB + Rechtsabteilung',
|
||||
}
|
||||
|
||||
const SDK_HEADERS = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Tenant-ID': '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e',
|
||||
'X-User-ID': '00000000-0000-0000-0000-000000000001',
|
||||
}
|
||||
|
||||
export function useAgentAnalysis() {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [result, setResult] = useState<AnalysisResult | null>(null)
|
||||
const [history, setHistory] = useState<AnalysisResult[]>([])
|
||||
|
||||
async function analyze(url: string) {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
setResult(null)
|
||||
|
||||
try {
|
||||
// Step 1: Fetch and classify
|
||||
const fetchRes = await fetch('/api/sdk/v1/agent/analyze', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ url }),
|
||||
})
|
||||
|
||||
if (!fetchRes.ok) {
|
||||
throw new Error(`Analyse fehlgeschlagen: ${fetchRes.status}`)
|
||||
}
|
||||
|
||||
const data = await fetchRes.json()
|
||||
const analysisResult: AnalysisResult = {
|
||||
url,
|
||||
classification: data.classification || 'unknown',
|
||||
risk_level: data.risk_level || 'unknown',
|
||||
risk_score: data.risk_score || 0,
|
||||
escalation_level: data.escalation_level || 'E0',
|
||||
responsible_role: ESCALATION_ROLES[data.escalation_level] || ESCALATION_ROLES.E0,
|
||||
findings: data.findings || [],
|
||||
required_controls: data.required_controls || [],
|
||||
summary: data.summary || '',
|
||||
email_status: data.email_status || 'pending',
|
||||
analyzed_at: new Date().toISOString(),
|
||||
}
|
||||
|
||||
setResult(analysisResult)
|
||||
setHistory(prev => [analysisResult, ...prev].slice(0, 20))
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : 'Unbekannter Fehler')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return { analyze, loading, error, result, history }
|
||||
}
|
||||
Reference in New Issue
Block a user