Add CLAUDE.md, MkDocs docs, docs page in admin, .claude/rules
- CLAUDE.md: Comprehensive documentation for Compliance SDK platform - docs-src: AI-Compliance-SDK docs (architecture, developer, auditor, SBOM) - mkdocs.yml: Compliance-specific nav with purple theme - docker-compose: Added docs service (port 8011, profile: docs) - admin-compliance: New /development/docs page with iframe + quick links - navigation.ts: Added development category with docs module - .claude/rules: testing, docs, open-source, compliance-checklist Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
188
admin-compliance/app/(admin)/development/docs/page.tsx
Normal file
188
admin-compliance/app/(admin)/development/docs/page.tsx
Normal file
@@ -0,0 +1,188 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { ExternalLink, Maximize2, Minimize2, RefreshCw, Search, BookOpen, ArrowRight } from 'lucide-react'
|
||||
|
||||
// Quick links to compliance documentation sections
|
||||
const quickLinks = [
|
||||
{ name: 'AI Compliance SDK', path: 'services/ai-compliance-sdk/', icon: '🔒' },
|
||||
{ name: 'Architektur', path: 'services/ai-compliance-sdk/ARCHITECTURE/', icon: '🏗️' },
|
||||
{ name: 'Developer Guide', path: 'services/ai-compliance-sdk/DEVELOPER/', icon: '👩💻' },
|
||||
{ name: 'Auditor Doku', path: 'services/ai-compliance-sdk/AUDITOR_DOCUMENTATION/', icon: '📋' },
|
||||
{ name: 'SBOM', path: 'services/ai-compliance-sdk/SBOM/', icon: '📦' },
|
||||
{ name: 'CI/CD Pipeline', path: 'development/ci-cd-pipeline/', icon: '🚀' },
|
||||
]
|
||||
|
||||
export default function DocsPage() {
|
||||
const [isFullscreen, setIsFullscreen] = useState(false)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [currentPath, setCurrentPath] = useState('')
|
||||
|
||||
const getDocsUrl = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const protocol = window.location.protocol
|
||||
const hostname = window.location.hostname
|
||||
const port = window.location.port
|
||||
return `${protocol}//${hostname}${port ? ':' + port : ''}/docs`
|
||||
}
|
||||
return '/docs'
|
||||
}
|
||||
|
||||
const docsUrl = getDocsUrl()
|
||||
|
||||
const handleIframeLoad = () => {
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
const navigateTo = (path: string) => {
|
||||
setCurrentPath(path)
|
||||
setIsLoading(true)
|
||||
}
|
||||
|
||||
const toggleFullscreen = () => {
|
||||
setIsFullscreen(!isFullscreen)
|
||||
}
|
||||
|
||||
const openInNewTab = () => {
|
||||
window.open(`${docsUrl}/${currentPath}`, '_blank')
|
||||
}
|
||||
|
||||
const refreshDocs = () => {
|
||||
setIsLoading(true)
|
||||
setCurrentPath(currentPath + '?refresh=' + Date.now())
|
||||
setTimeout(() => setCurrentPath(currentPath), 100)
|
||||
}
|
||||
|
||||
if (isFullscreen) {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 bg-white">
|
||||
<div className="absolute top-0 left-0 right-0 h-12 bg-slate-900 flex items-center justify-between px-4 z-10">
|
||||
<div className="flex items-center gap-2 text-white">
|
||||
<BookOpen className="w-5 h-5" />
|
||||
<span className="font-semibold">BreakPilot Compliance Dokumentation</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={openInNewTab}
|
||||
className="p-2 text-slate-300 hover:text-white hover:bg-slate-700 rounded transition-colors"
|
||||
title="In neuem Tab oeffnen"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={toggleFullscreen}
|
||||
className="p-2 text-slate-300 hover:text-white hover:bg-slate-700 rounded transition-colors"
|
||||
title="Vollbild beenden"
|
||||
>
|
||||
<Minimize2 className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<iframe
|
||||
src={`${docsUrl}/${currentPath}`}
|
||||
className="w-full h-full pt-12"
|
||||
title="BreakPilot Compliance Documentation"
|
||||
onLoad={handleIframeLoad}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Quick Links */}
|
||||
<div className="bg-white border border-slate-200 rounded-xl p-4">
|
||||
<h3 className="text-sm font-semibold text-slate-700 mb-3 flex items-center gap-2">
|
||||
<Search className="w-4 h-4" />
|
||||
Schnellzugriff
|
||||
</h3>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-2">
|
||||
{quickLinks.map((link) => (
|
||||
<button
|
||||
key={link.path}
|
||||
onClick={() => navigateTo(link.path)}
|
||||
className="flex items-center gap-2 px-3 py-2 text-sm bg-slate-50 hover:bg-slate-100 border border-slate-200 rounded-lg transition-colors text-left"
|
||||
>
|
||||
<span>{link.icon}</span>
|
||||
<span className="truncate">{link.name}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Toolbar */}
|
||||
<div className="flex items-center justify-between bg-white border border-slate-200 rounded-xl p-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<BookOpen className="w-5 h-5 text-slate-500" />
|
||||
<span className="text-sm font-medium text-slate-700">
|
||||
BreakPilot Compliance Dokumentation
|
||||
</span>
|
||||
<span className="text-xs text-slate-400">
|
||||
(MkDocs Material)
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={refreshDocs}
|
||||
className="p-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg transition-colors"
|
||||
title="Aktualisieren"
|
||||
>
|
||||
<RefreshCw className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
|
||||
</button>
|
||||
<button
|
||||
onClick={openInNewTab}
|
||||
className="p-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg transition-colors"
|
||||
title="In neuem Tab oeffnen"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={toggleFullscreen}
|
||||
className="p-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg transition-colors"
|
||||
title="Vollbild"
|
||||
>
|
||||
<Maximize2 className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Documentation Iframe */}
|
||||
<div className="relative bg-white border border-slate-200 rounded-xl overflow-hidden" style={{ height: 'calc(100vh - 350px)', minHeight: '500px' }}>
|
||||
{isLoading && (
|
||||
<div className="absolute inset-0 bg-white flex items-center justify-center z-10">
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<div className="w-8 h-8 border-2 border-slate-300 border-t-slate-600 rounded-full animate-spin" />
|
||||
<span className="text-sm text-slate-500">Dokumentation wird geladen...</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<iframe
|
||||
key={currentPath}
|
||||
src={`${docsUrl}/${currentPath}`}
|
||||
className="w-full h-full"
|
||||
title="BreakPilot Compliance Documentation"
|
||||
onLoad={handleIframeLoad}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Info Box */}
|
||||
<div className="bg-slate-50 border border-slate-200 rounded-xl p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="p-2 bg-slate-200 rounded-lg">
|
||||
<ArrowRight className="w-4 h-4 text-slate-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-medium text-slate-800">Dokumentation bearbeiten</h4>
|
||||
<p className="text-sm text-slate-600 mt-1">
|
||||
Die Dokumentation befindet sich im Repository unter <code className="text-xs bg-slate-200 px-1.5 py-0.5 rounded">docs-src/</code>.
|
||||
Nach Aenderungen muss der Docs-Container neu gebaut werden:
|
||||
</p>
|
||||
<div className="mt-2 text-xs text-slate-500 font-mono bg-slate-100 p-2 rounded">
|
||||
docker compose --profile docs build docs && docker compose --profile docs up -d docs
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -8,6 +8,15 @@ import type {
|
||||
CatalogFieldSchema,
|
||||
} from '@/lib/sdk/catalog-manager/types'
|
||||
|
||||
// Resolve localized text objects to German string for display
|
||||
function resolveDisplayValue(value: unknown): unknown {
|
||||
if (value === null || value === undefined) return value
|
||||
if (typeof value === 'object' && !Array.isArray(value) && 'de' in (value as Record<string, unknown>)) {
|
||||
return String((value as Record<string, string>).de || '')
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
interface CatalogEntryFormProps {
|
||||
catalog: CatalogMeta
|
||||
entry?: CatalogEntry | null
|
||||
@@ -39,7 +48,7 @@ export default function CatalogEntryForm({
|
||||
if (isEditMode && entry) {
|
||||
const initialData: Record<string, unknown> = {}
|
||||
for (const field of catalog.fields) {
|
||||
initialData[field.key] = entry.data?.[field.key] ?? getDefaultValue(field)
|
||||
initialData[field.key] = resolveDisplayValue(entry.data?.[field.key]) ?? getDefaultValue(field)
|
||||
}
|
||||
setFormData(initialData)
|
||||
} else {
|
||||
|
||||
@@ -66,7 +66,7 @@ interface CategoryCardProps {
|
||||
export function CategoryCard({ category, showModuleCount = true }: CategoryCardProps) {
|
||||
return (
|
||||
<Link
|
||||
href={`/${category.id}`}
|
||||
href={category.id === 'compliance-sdk' ? '/sdk' : `/${category.id}`}
|
||||
className="block p-6 rounded-xl border-2 transition-all hover:shadow-lg bg-white"
|
||||
style={{
|
||||
borderColor: `${category.color}40`,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Extracted from admin-v2, keeping only compliance-relevant modules.
|
||||
*/
|
||||
|
||||
export type CategoryId = 'compliance-sdk'
|
||||
export type CategoryId = 'compliance-sdk' | 'development'
|
||||
|
||||
export interface NavModule {
|
||||
id: string
|
||||
@@ -15,8 +15,8 @@ export interface NavModule {
|
||||
purpose: string
|
||||
audience: string[]
|
||||
gdprArticles?: string[]
|
||||
oldAdminPath?: string // Reference to old admin for migration
|
||||
subgroup?: string // Optional subgroup for visual grouping in sidebar
|
||||
oldAdminPath?: string
|
||||
subgroup?: string
|
||||
}
|
||||
|
||||
export interface NavCategory {
|
||||
@@ -51,6 +51,27 @@ export const navigation: NavCategory[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
// =========================================================================
|
||||
// Development - Entwickler-Tools und Dokumentation
|
||||
// =========================================================================
|
||||
{
|
||||
id: 'development',
|
||||
name: 'Entwicklung',
|
||||
icon: 'code',
|
||||
color: '#0ea5e9', // Sky-500
|
||||
colorClass: 'development',
|
||||
description: 'Dokumentation & Entwickler-Tools',
|
||||
modules: [
|
||||
{
|
||||
id: 'docs',
|
||||
name: 'Dokumentation',
|
||||
href: '/development/docs',
|
||||
description: 'MkDocs Projekt-Dokumentation',
|
||||
purpose: 'Technische Dokumentation der Compliance-Plattform mit Architektur, API-Referenz und Entwickler-Guides.',
|
||||
audience: ['Entwickler', 'Architekten'],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// Meta modules (always visible)
|
||||
|
||||
@@ -298,9 +298,78 @@ export const CATALOG_REGISTRY: Record<CatalogId, CatalogMeta> = {
|
||||
{ key: 'id', label: 'ID', type: 'text', required: true },
|
||||
{ key: 'name', label: 'Name', type: 'text', required: true },
|
||||
{ key: 'description', label: 'Beschreibung', type: 'textarea', required: true },
|
||||
{ key: 'serviceCategory', label: 'Kategorie', type: 'text', required: true },
|
||||
{ key: 'serviceCategory', label: 'Dienstleistungskategorie', type: 'select', required: true, options: [
|
||||
{ value: 'HOSTING', label: 'Hosting' },
|
||||
{ value: 'CLOUD_INFRASTRUCTURE', label: 'Cloud-Infrastruktur' },
|
||||
{ value: 'ANALYTICS', label: 'Analyse' },
|
||||
{ value: 'CRM', label: 'CRM' },
|
||||
{ value: 'ERP', label: 'ERP' },
|
||||
{ value: 'HR_SOFTWARE', label: 'HR-Software' },
|
||||
{ value: 'PAYMENT', label: 'Zahlungsdienstleister' },
|
||||
{ value: 'EMAIL', label: 'E-Mail' },
|
||||
{ value: 'MARKETING', label: 'Marketing' },
|
||||
{ value: 'SUPPORT', label: 'Support' },
|
||||
{ value: 'SECURITY', label: 'Sicherheit' },
|
||||
{ value: 'COMMUNICATION', label: 'Kommunikation' },
|
||||
{ value: 'STORAGE', label: 'Speicher' },
|
||||
{ value: 'BACKUP', label: 'Backup' },
|
||||
{ value: 'CDN', label: 'CDN' },
|
||||
{ value: 'ACCOUNTING', label: 'Buchhaltung' },
|
||||
{ value: 'CONSULTING', label: 'Beratung' },
|
||||
{ value: 'OTHER', label: 'Sonstige' },
|
||||
]},
|
||||
{ key: 'suggestedRole', label: 'Vorgeschlagene Rolle', type: 'select', required: false, options: [
|
||||
{ value: 'PROCESSOR', label: 'Auftragsverarbeiter' },
|
||||
{ value: 'JOINT_CONTROLLER', label: 'Gemeinsam Verantwortlicher' },
|
||||
{ value: 'CONTROLLER', label: 'Eigenstaendiger Verantwortlicher' },
|
||||
{ value: 'SUB_PROCESSOR', label: 'Unterauftragnehmer' },
|
||||
{ value: 'THIRD_PARTY', label: 'Dritter' },
|
||||
]},
|
||||
{ key: 'suggestedDataAccess', label: 'Datenzugriff', type: 'select', required: false, options: [
|
||||
{ value: 'NONE', label: 'Kein Zugriff' },
|
||||
{ value: 'POTENTIAL', label: 'Potenzieller Zugriff' },
|
||||
{ value: 'ADMINISTRATIVE', label: 'Administrativer Zugriff' },
|
||||
{ value: 'CONTENT', label: 'Inhaltlicher Zugriff' },
|
||||
]},
|
||||
{ key: 'suggestedTransferMechanisms', label: 'Transfer-Mechanismen', type: 'multiselect', required: false, options: [
|
||||
{ value: 'ADEQUACY_DECISION', label: 'Angemessenheitsbeschluss' },
|
||||
{ value: 'SCC_CONTROLLER', label: 'SCC Controller-to-Controller' },
|
||||
{ value: 'SCC_PROCESSOR', label: 'SCC Controller-to-Processor' },
|
||||
{ value: 'BCR', label: 'Binding Corporate Rules' },
|
||||
{ value: 'DEROGATION_CONSENT', label: 'Einwilligung' },
|
||||
{ value: 'DEROGATION_CONTRACT', label: 'Vertragserfuellung' },
|
||||
{ value: 'CERTIFICATION', label: 'Zertifizierung' },
|
||||
{ value: 'CODE_OF_CONDUCT', label: 'Verhaltensregeln' },
|
||||
]},
|
||||
{ key: 'suggestedContractTypes', label: 'Vertragstypen', type: 'multiselect', required: false, options: [
|
||||
{ value: 'AVV', label: 'AVV (Auftragsverarbeitung)' },
|
||||
{ value: 'MSA', label: 'MSA (Master Service)' },
|
||||
{ value: 'SLA', label: 'SLA (Service Level)' },
|
||||
{ value: 'SCC', label: 'SCC (Standardvertragsklauseln)' },
|
||||
{ value: 'NDA', label: 'NDA (Geheimhaltung)' },
|
||||
{ value: 'TOM_ANNEX', label: 'TOM-Anlage' },
|
||||
{ value: 'CERTIFICATION', label: 'Zertifikat' },
|
||||
{ value: 'SUB_PROCESSOR_LIST', label: 'Unterauftragnehmer-Liste' },
|
||||
]},
|
||||
{ key: 'typicalDataCategories', label: 'Typische Datenkategorien', type: 'multiselect', required: false, options: [
|
||||
{ value: 'NAME', label: 'Name' },
|
||||
{ value: 'CONTACT', label: 'Kontaktdaten' },
|
||||
{ value: 'ADDRESS', label: 'Adressdaten' },
|
||||
{ value: 'DOB', label: 'Geburtsdatum' },
|
||||
{ value: 'BANK_ACCOUNT', label: 'Bankverbindung' },
|
||||
{ value: 'PAYMENT_DATA', label: 'Zahlungsdaten' },
|
||||
{ value: 'EMPLOYMENT_DATA', label: 'Beschaeftigungsdaten' },
|
||||
{ value: 'SALARY_DATA', label: 'Gehaltsdaten' },
|
||||
{ value: 'HEALTH_DATA', label: 'Gesundheitsdaten' },
|
||||
{ value: 'IP_ADDRESS', label: 'IP-Adresse' },
|
||||
{ value: 'USAGE_DATA', label: 'Nutzungsdaten' },
|
||||
{ value: 'LOCATION_DATA', label: 'Standortdaten' },
|
||||
{ value: 'COMMUNICATION_DATA', label: 'Kommunikationsdaten' },
|
||||
]},
|
||||
{ key: 'typicalCertifications', label: 'Typische Zertifizierungen', type: 'tags', required: false, placeholder: 'z.B. ISO 27001, SOC 2, C5' },
|
||||
{ key: 'commonProviders', label: 'Typische Anbieter', type: 'tags', required: false, placeholder: 'z.B. AWS, Azure, GCP' },
|
||||
],
|
||||
searchableFields: ['id', 'name', 'description', 'serviceCategory'],
|
||||
searchableFields: ['id', 'name', 'description', 'serviceCategory', 'suggestedRole', 'commonProviders'],
|
||||
},
|
||||
|
||||
'country-risk-profiles': {
|
||||
|
||||
Reference in New Issue
Block a user