feat(training+controls): interactive video pipeline, training blocks, control generator, CE libraries
Some checks failed
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Failing after 37s
CI/CD / test-python-backend-compliance (push) Successful in 39s
CI/CD / test-python-document-crawler (push) Successful in 26s
CI/CD / test-python-dsms-gateway (push) Successful in 23s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Has been skipped

Interactive Training Videos (CP-TRAIN):
- DB migration 022: training_checkpoints + checkpoint_progress tables
- NarratorScript generation via Anthropic (AI Teacher persona, German)
- TTS batch synthesis + interactive video pipeline (slides + checkpoint slides + FFmpeg)
- 4 new API endpoints: generate-interactive, interactive-manifest, checkpoint submit, checkpoint progress
- InteractiveVideoPlayer component (HTML5 Video, quiz overlay, seek protection, progress tracking)
- Learner portal integration with automatic completion on all checkpoints passed
- 30 new tests (handler validation + grading logic + manifest/progress + seek protection)

Training Blocks:
- Block generator, block store, block config CRUD + preview/generate endpoints
- Migration 021: training_blocks schema

Control Generator + Canonical Library:
- Control generator routes + service enhancements
- Canonical control library helpers, sidebar entry
- Citation backfill service + tests
- CE libraries data (hazard, protection, evidence, lifecycle, components)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-16 21:41:48 +01:00
parent d2133dbfa2
commit 4f6bc8f6f6
50 changed files with 17299 additions and 198 deletions

View File

@@ -0,0 +1,439 @@
'use client'
import { DevPortalLayout, ApiEndpoint, CodeBlock, ParameterTable, InfoBox } from '@/components/DevPortalLayout'
export default function TrainingAPIPage() {
return (
<DevPortalLayout
title="Training API"
description="Compliance-Schulungssystem (CP-TRAIN) — Module, Zuweisungen, Quiz, Zertifikate, KI-Generierung"
>
{/* ================================================================= */}
{/* OVERVIEW */}
{/* ================================================================= */}
<h2>Uebersicht</h2>
<p>
Das Training-Modul bietet ein vollstaendiges Compliance-Schulungssystem mit:
</p>
<ul>
<li>Modulverwaltung mit Regulierungsbereichen (DSGVO, NIS2, ISO 27001, AI Act, GeschGehG, HinSchG)</li>
<li>Compliance Training Matrix (CTM) rollenbasierte Zuweisung</li>
<li>KI-gestuetzte Content- und Quiz-Generierung</li>
<li>Audio/Video-Schulungsinhalte via TTS</li>
<li>Quiz-Engine mit Bestehens-Schwelle</li>
<li>Eskalationsstufen (7/14/30/45 Tage)</li>
<li>PDF-Zertifikate nach Schulungsabschluss</li>
<li>Training Blocks automatische Modul-Erstellung aus Canonical Controls</li>
</ul>
<InfoBox type="info" title="Basis-URL">
Alle Endpoints nutzen den Prefix <code>/sdk/v1/training</code>.
Authentifizierung via <code>X-Tenant-ID</code> und <code>X-User-ID</code> Header.
</InfoBox>
{/* ================================================================= */}
{/* MODULES */}
{/* ================================================================= */}
<h2 id="modules">1. Module</h2>
<p>Schulungsmodule sind die zentrale Einheit des Training-Systems.</p>
<ApiEndpoint method="GET" path="/sdk/v1/training/modules" description="Alle Module auflisten (mit optionalen Filtern)" />
<ParameterTable parameters={[
{ name: 'regulation_area', type: 'string', description: 'Filter: dsgvo, nis2, iso27001, ai_act, geschgehg, hinschg' },
{ name: 'frequency_type', type: 'string', description: 'Filter: onboarding, annual, event_trigger, micro' },
{ name: 'search', type: 'string', description: 'Volltextsuche in Titel und Beschreibung' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/modules/:id" description="Einzelnes Modul mit Content und Quiz-Fragen laden" />
<ApiEndpoint method="POST" path="/sdk/v1/training/modules" description="Neues Schulungsmodul erstellen" />
<ParameterTable parameters={[
{ name: 'module_code', type: 'string', required: true, description: 'Eindeutiger Modulcode (z.B. CP-TRAIN-001)' },
{ name: 'title', type: 'string', required: true, description: 'Titel des Moduls' },
{ name: 'description', type: 'string', description: 'Beschreibung' },
{ name: 'regulation_area', type: 'string', required: true, description: 'Regulierungsbereich' },
{ name: 'frequency_type', type: 'string', required: true, description: 'Schulungsfrequenz' },
{ name: 'duration_minutes', type: 'integer', description: 'Dauer in Minuten (Standard: 30)' },
{ name: 'pass_threshold', type: 'integer', description: 'Quiz-Bestehensgrenze in Prozent (Standard: 70)' },
]} />
<ApiEndpoint method="PUT" path="/sdk/v1/training/modules/:id" description="Modul aktualisieren" />
<ApiEndpoint method="DELETE" path="/sdk/v1/training/modules/:id" description="Modul loeschen" />
<CodeBlock language="json">{`// POST /sdk/v1/training/modules — Beispiel
{
"module_code": "CP-DSGVO-001",
"title": "DSGVO Grundlagen fuer Mitarbeiter",
"description": "Einfuehrung in die Datenschutz-Grundverordnung",
"regulation_area": "dsgvo",
"frequency_type": "annual",
"duration_minutes": 30,
"pass_threshold": 70
}`}</CodeBlock>
{/* ================================================================= */}
{/* MATRIX */}
{/* ================================================================= */}
<h2 id="matrix">2. Compliance Training Matrix (CTM)</h2>
<p>Die CTM ordnet Rollen zu Schulungsmodulen zu. 10 vordefinierte Rollen (R1R10).</p>
<ApiEndpoint method="GET" path="/sdk/v1/training/matrix" description="Vollstaendige Training-Matrix abrufen (alle Rollen → Module)" />
<ApiEndpoint method="GET" path="/sdk/v1/training/matrix/:role" description="Module fuer eine bestimmte Rolle abrufen" />
<ApiEndpoint method="POST" path="/sdk/v1/training/matrix" description="Matrix-Eintrag setzen (Rolle → Modul)" />
<ParameterTable parameters={[
{ name: 'role_code', type: 'string', required: true, description: 'Rollencode (R1R10)' },
{ name: 'module_id', type: 'uuid', required: true, description: 'Modul-UUID' },
{ name: 'is_mandatory', type: 'boolean', description: 'Pflichtschulung (Standard: false)' },
{ name: 'priority', type: 'integer', description: 'Prioritaet (1 = hoechste)' },
]} />
<ApiEndpoint method="DELETE" path="/sdk/v1/training/matrix/:role/:moduleId" description="Matrix-Eintrag entfernen" />
<InfoBox type="info" title="Rollen">
R1: Geschaeftsfuehrung, R2: IT-Leitung, R3: DSB, R4: ISB, R5: HR,
R6: Einkauf, R7: Fachabteilung, R8: IT-Admin, R9: Alle Mitarbeiter, R10: Behoerden
</InfoBox>
{/* ================================================================= */}
{/* ASSIGNMENTS */}
{/* ================================================================= */}
<h2 id="assignments">3. Zuweisungen</h2>
<p>Zuweisungen verbinden Mitarbeiter mit Schulungsmodulen und tracken den Fortschritt.</p>
<ApiEndpoint method="POST" path="/sdk/v1/training/assignments/compute" description="Zuweisungen fuer einen Benutzer berechnen (basierend auf Rollen + CTM)" />
<ParameterTable parameters={[
{ name: 'user_id', type: 'uuid', required: true, description: 'Benutzer-UUID' },
{ name: 'user_name', type: 'string', required: true, description: 'Name des Benutzers' },
{ name: 'user_email', type: 'string', required: true, description: 'E-Mail' },
{ name: 'roles', type: 'string[]', required: true, description: 'Rollencodes des Benutzers' },
{ name: 'trigger', type: 'string', description: 'Ausloeser: onboarding, annual, event, manual' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/assignments" description="Zuweisungen auflisten" />
<ParameterTable parameters={[
{ name: 'user_id', type: 'uuid', description: 'Filter nach Benutzer' },
{ name: 'module_id', type: 'uuid', description: 'Filter nach Modul' },
{ name: 'role', type: 'string', description: 'Filter nach Rolle' },
{ name: 'status', type: 'string', description: 'Filter: pending, in_progress, completed, overdue, expired' },
{ name: 'limit', type: 'integer', description: 'Pagination (Standard: 50)' },
{ name: 'offset', type: 'integer', description: 'Pagination Offset' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/assignments/:id" description="Einzelne Zuweisung laden" />
<ApiEndpoint method="PUT" path="/sdk/v1/training/assignments/:id" description="Zuweisung aktualisieren (z.B. Deadline aendern)" />
<ApiEndpoint method="POST" path="/sdk/v1/training/assignments/:id/start" description="Schulung starten (Status → in_progress)" />
<ApiEndpoint method="POST" path="/sdk/v1/training/assignments/:id/progress" description="Fortschritt aktualisieren (0100%)" />
<ApiEndpoint method="POST" path="/sdk/v1/training/assignments/:id/complete" description="Schulung abschliessen (Status → completed)" />
<CodeBlock language="json">{`// POST /sdk/v1/training/assignments/compute — Response
{
"assignments": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"module_id": "...",
"user_id": "...",
"status": "pending",
"progress_percent": 0,
"deadline": "2026-04-15T00:00:00Z",
"escalation_level": 0
}
],
"created": 5
}`}</CodeBlock>
{/* ================================================================= */}
{/* QUIZ */}
{/* ================================================================= */}
<h2 id="quiz">4. Quiz-Engine</h2>
<p>Multiple-Choice-Quiz mit automatischer Bewertung und Bestehensgrenze.</p>
<ApiEndpoint method="GET" path="/sdk/v1/training/quiz/:moduleId" description="Quiz-Fragen fuer ein Modul abrufen" />
<ApiEndpoint method="POST" path="/sdk/v1/training/quiz/:moduleId/submit" description="Quiz-Antworten einreichen" />
<ParameterTable parameters={[
{ name: 'assignment_id', type: 'uuid', required: true, description: 'Zuweisungs-UUID' },
{ name: 'answers', type: 'QuizAnswer[]', required: true, description: 'Array von {question_id, selected_index}' },
{ name: 'duration_seconds', type: 'integer', description: 'Bearbeitungsdauer in Sekunden' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/quiz/attempts/:assignmentId" description="Quiz-Versuche fuer eine Zuweisung anzeigen" />
<CodeBlock language="json">{`// POST /sdk/v1/training/quiz/:moduleId/submit — Response
{
"attempt_id": "...",
"score": 80.0,
"passed": true,
"correct_count": 4,
"total_count": 5,
"threshold": 70
}`}</CodeBlock>
{/* ================================================================= */}
{/* CONTENT GENERATION */}
{/* ================================================================= */}
<h2 id="content">5. KI-Content-Generierung</h2>
<p>LLM-basierte Erstellung von Schulungsinhalten und Quiz-Fragen.</p>
<ApiEndpoint method="POST" path="/sdk/v1/training/content/generate" description="Schulungsinhalt fuer ein Modul generieren (Markdown)" />
<ParameterTable parameters={[
{ name: 'module_id', type: 'uuid', required: true, description: 'Modul-UUID' },
{ name: 'language', type: 'string', description: 'Sprache: de (Standard) oder en' },
]} />
<ApiEndpoint method="POST" path="/sdk/v1/training/content/generate-quiz" description="Quiz-Fragen fuer ein Modul generieren" />
<ParameterTable parameters={[
{ name: 'module_id', type: 'uuid', required: true, description: 'Modul-UUID' },
{ name: 'count', type: 'integer', description: 'Anzahl Fragen (Standard: 5)' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/content/:moduleId" description="Veroeffentlichten Content eines Moduls abrufen" />
<ApiEndpoint method="POST" path="/sdk/v1/training/content/:contentId/publish" description="Content veroeffentlichen (Freigabe)" />
<ApiEndpoint method="POST" path="/sdk/v1/training/content/generate-all" description="Content fuer alle Module ohne Content generieren (Bulk)" />
<ApiEndpoint method="POST" path="/sdk/v1/training/content/generate-all-quiz" description="Quiz fuer alle Module ohne Fragen generieren (Bulk)" />
<InfoBox type="warning" title="LLM-Kosten">
Content- und Quiz-Generierung nutzt LLM-APIs (Ollama/Anthropic). Bulk-Generierung kann
signifikante Token-Kosten verursachen. PII-Detektion ist aktiv personenbezogene Daten
werden automatisch redaktiert.
</InfoBox>
{/* ================================================================= */}
{/* MEDIA */}
{/* ================================================================= */}
<h2 id="media">6. Media (Audio/Video)</h2>
<p>TTS-basierte Audio- und Videogenerierung fuer Schulungsmodule.</p>
<ApiEndpoint method="POST" path="/sdk/v1/training/content/:moduleId/generate-audio" description="Audio-Datei aus Schulungsinhalt generieren (Piper TTS)" />
<ApiEndpoint method="POST" path="/sdk/v1/training/content/:moduleId/generate-video" description="Praesentationsvideo generieren (TTS + Folien)" />
<ApiEndpoint method="POST" path="/sdk/v1/training/content/:moduleId/preview-script" description="Video-Script als JSON-Vorschau generieren" />
<ApiEndpoint method="GET" path="/sdk/v1/training/media/module/:moduleId" description="Alle Medien eines Moduls auflisten" />
<ApiEndpoint method="GET" path="/sdk/v1/training/media/:mediaId/url" description="Metadaten (Bucket, Object Key) fuer eine Media-Datei" />
<ApiEndpoint method="POST" path="/sdk/v1/training/media/:mediaId/publish" description="Media veroeffentlichen/zurueckziehen" />
<ApiEndpoint method="GET" path="/sdk/v1/training/media/:mediaId/stream" description="Media streamen (307-Redirect zu Presigned URL)" />
<InfoBox type="info" title="Streaming">
Der <code>/stream</code>-Endpoint liefert einen <code>307 Temporary Redirect</code> zu einer
zeitlich begrenzten Presigned URL (MinIO/S3). Browser und Audio/Video-Player folgen dem
Redirect automatisch.
</InfoBox>
<CodeBlock language="json">{`// POST /sdk/v1/training/content/:moduleId/preview-script — Response
{
"title": "DSGVO Grundlagen",
"sections": [
{
"heading": "Was ist die DSGVO?",
"text": "Die DSGVO regelt den Umgang mit personenbezogenen Daten.",
"bullet_points": [
"Gilt seit 25. Mai 2018",
"EU-weit verbindlich",
"Hohe Bussgelder bei Verstoessen"
]
}
]
}`}</CodeBlock>
{/* ================================================================= */}
{/* DEADLINES & ESCALATION */}
{/* ================================================================= */}
<h2 id="deadlines">7. Deadlines & Eskalation</h2>
<p>Automatisches Eskalationssystem mit 4 Stufen.</p>
<ApiEndpoint method="GET" path="/sdk/v1/training/deadlines" description="Anstehende Deadlines auflisten" />
<ParameterTable parameters={[
{ name: 'limit', type: 'integer', description: 'Maximale Anzahl (Standard: 50)' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/deadlines/overdue" description="Ueberfaellige Zuweisungen auflisten" />
<ApiEndpoint method="POST" path="/sdk/v1/training/escalation/check" description="Eskalationspruefung ausfuehren" />
<CodeBlock language="json">{`// POST /sdk/v1/training/escalation/check — Response
{
"results": [
{
"assignment_id": "...",
"user_name": "Max Mustermann",
"module_title": "DSGVO Grundlagen",
"previous_level": 1,
"new_level": 2,
"days_overdue": 15,
"escalation_label": "Benachrichtigung Teamleitung"
}
],
"total_checked": 42,
"escalated": 3
}`}</CodeBlock>
<ParameterTable parameters={[
{ name: 'Stufe 1 (7 Tage)', type: '-', description: 'Erinnerung an Mitarbeiter' },
{ name: 'Stufe 2 (14 Tage)', type: '-', description: 'Benachrichtigung Teamleitung' },
{ name: 'Stufe 3 (30 Tage)', type: '-', description: 'Benachrichtigung Management' },
{ name: 'Stufe 4 (45 Tage)', type: '-', description: 'Benachrichtigung Compliance Officer' },
]} />
{/* ================================================================= */}
{/* CERTIFICATES */}
{/* ================================================================= */}
<h2 id="certificates">8. Zertifikate</h2>
<p>PDF-Zertifikate nach erfolgreichem Schulungsabschluss.</p>
<ApiEndpoint method="POST" path="/sdk/v1/training/certificates/generate/:assignmentId" description="Zertifikat fuer eine abgeschlossene Zuweisung generieren" />
<ApiEndpoint method="GET" path="/sdk/v1/training/certificates" description="Alle Zertifikate des Tenants auflisten" />
<ApiEndpoint method="GET" path="/sdk/v1/training/certificates/:id/pdf" description="Zertifikat als PDF herunterladen" />
<ApiEndpoint method="GET" path="/sdk/v1/training/certificates/:id/verify" description="Zertifikat verifizieren (z.B. fuer Audit)" />
<InfoBox type="warning" title="Voraussetzungen">
Zertifikate koennen nur generiert werden, wenn die Zuweisung den Status <code>completed</code> hat
UND das Quiz bestanden wurde (<code>quiz_passed = true</code>).
</InfoBox>
<CodeBlock language="json">{`// POST /sdk/v1/training/certificates/generate/:assignmentId — Response
{
"certificate_id": "a1b2c3d4-...",
"assignment": {
"id": "...",
"status": "completed",
"quiz_passed": true,
"certificate_id": "a1b2c3d4-...",
"module_title": "DSGVO Grundlagen"
}
}
// GET /sdk/v1/training/certificates/:id/verify — Response
{
"valid": true,
"assignment": { ... }
}`}</CodeBlock>
{/* ================================================================= */}
{/* AUDIT & STATS */}
{/* ================================================================= */}
<h2 id="audit">9. Audit & Statistiken</h2>
<p>Compliance-konformes Audit-Logging aller Schulungsaktivitaeten.</p>
<ApiEndpoint method="GET" path="/sdk/v1/training/audit-log" description="Audit-Log abrufen" />
<ParameterTable parameters={[
{ name: 'action', type: 'string', description: 'Filter: assigned, started, completed, quiz_submitted, escalated, certificate_issued, content_generated' },
{ name: 'entity_type', type: 'string', description: 'Filter: assignment, module, quiz, certificate' },
{ name: 'limit', type: 'integer', description: 'Pagination (Standard: 50)' },
{ name: 'offset', type: 'integer', description: 'Pagination Offset' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/stats" description="Aggregierte Schulungsstatistiken" />
<CodeBlock language="json">{`// GET /sdk/v1/training/stats — Response
{
"total_modules": 28,
"total_assignments": 156,
"completion_rate": 72.5,
"overdue_count": 8,
"pending_count": 23,
"in_progress_count": 14,
"completed_count": 111,
"avg_quiz_score": 81.3,
"avg_completion_days": 4.2,
"upcoming_deadlines": 12
}`}</CodeBlock>
{/* ================================================================= */}
{/* TRAINING BLOCKS */}
{/* ================================================================= */}
<h2 id="blocks">10. Training Blocks (Controls Module)</h2>
<p>
Training Blocks automatisieren die Erstellung von Schulungsmodulen aus Canonical Controls.
Ein Block definiert Filter (Domain, Kategorie, Severity, Zielgruppe) und generiert
automatisch Module, Content und CTM-Eintraege.
</p>
<ApiEndpoint method="GET" path="/sdk/v1/training/blocks" description="Alle Block-Konfigurationen auflisten" />
<ApiEndpoint method="POST" path="/sdk/v1/training/blocks" description="Neue Block-Konfiguration erstellen" />
<ParameterTable parameters={[
{ name: 'name', type: 'string', required: true, description: 'Name des Blocks' },
{ name: 'description', type: 'string', description: 'Beschreibung' },
{ name: 'domain_filter', type: 'string', description: 'Domain-Filter (z.B. AUTH, CRYP, NET)' },
{ name: 'category_filter', type: 'string', description: 'Kategorie-Filter (z.B. authentication, encryption)' },
{ name: 'severity_filter', type: 'string', description: 'Severity-Filter (high, critical)' },
{ name: 'target_audience_filter', type: 'string', description: 'Zielgruppe: enterprise, authority, provider, all' },
{ name: 'regulation_area', type: 'string', required: true, description: 'Regulierungsbereich' },
{ name: 'module_code_prefix', type: 'string', required: true, description: 'Prefix fuer generierte Modulcodes' },
{ name: 'frequency_type', type: 'string', description: 'Schulungsfrequenz' },
{ name: 'duration_minutes', type: 'integer', description: 'Dauer pro Modul' },
{ name: 'pass_threshold', type: 'integer', description: 'Quiz-Bestehensgrenze' },
{ name: 'max_controls_per_module', type: 'integer', description: 'Max. Controls pro Modul (Standard: 10)' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/blocks/:id" description="Block-Konfiguration laden" />
<ApiEndpoint method="PUT" path="/sdk/v1/training/blocks/:id" description="Block-Konfiguration aktualisieren" />
<ApiEndpoint method="DELETE" path="/sdk/v1/training/blocks/:id" description="Block-Konfiguration loeschen" />
<ApiEndpoint method="POST" path="/sdk/v1/training/blocks/:id/preview" description="Vorschau: Welche Controls und Module wuerden generiert?" />
<ApiEndpoint method="POST" path="/sdk/v1/training/blocks/:id/generate" description="Module aus Block generieren (Content + CTM)" />
<ParameterTable parameters={[
{ name: 'language', type: 'string', description: 'Sprache: de (Standard) oder en' },
{ name: 'auto_matrix', type: 'boolean', description: 'Automatisch CTM-Eintraege erstellen (Standard: true)' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/blocks/:id/controls" description="Verlinkte Controls eines Blocks anzeigen" />
<CodeBlock language="json">{`// POST /sdk/v1/training/blocks/:id/generate — Response
{
"modules_created": 3,
"controls_linked": 24,
"matrix_entries_created": 15,
"content_generated": 3,
"errors": []
}`}</CodeBlock>
{/* ================================================================= */}
{/* CANONICAL CONTROLS */}
{/* ================================================================= */}
<h2 id="canonical">11. Canonical Controls</h2>
<p>Referenz-Datenbank mit standardisierten Sicherheitskontrollen.</p>
<ApiEndpoint method="GET" path="/sdk/v1/training/canonical/controls" description="Canonical Controls auflisten (mit Filtern)" />
<ParameterTable parameters={[
{ name: 'domain', type: 'string', description: 'Domain-Filter (z.B. AUTH, CRYP)' },
{ name: 'category', type: 'string', description: 'Kategorie-Filter' },
{ name: 'severity', type: 'string', description: 'Severity-Filter' },
{ name: 'target_audience', type: 'string', description: 'Zielgruppen-Filter' },
]} />
<ApiEndpoint method="GET" path="/sdk/v1/training/canonical/meta" description="Aggregierte Metadaten (Domains, Kategorien, Audiences mit Counts)" />
<CodeBlock language="json">{`// GET /sdk/v1/training/canonical/meta — Response
{
"domains": [
{ "domain": "AUTH", "count": 12 },
{ "domain": "CRYP", "count": 8 }
],
"categories": [
{ "category": "authentication", "count": 12 },
{ "category": "encryption", "count": 8 }
],
"audiences": [
{ "audience": "enterprise", "count": 45 },
{ "audience": "all", "count": 30 }
],
"total": 102
}`}</CodeBlock>
{/* ================================================================= */}
{/* WORKFLOW */}
{/* ================================================================= */}
<h2 id="workflow">Typischer Workflow</h2>
<ol>
<li><strong>Module erstellen</strong> via POST /modules oder Training Blocks</li>
<li><strong>Content generieren</strong> POST /content/generate (LLM)</li>
<li><strong>Content freigeben</strong> POST /content/:id/publish</li>
<li><strong>Quiz generieren</strong> POST /content/generate-quiz</li>
<li><strong>Audio/Video</strong> POST /content/:id/generate-audio, generate-video</li>
<li><strong>CTM konfigurieren</strong> POST /matrix (Rolle Modul)</li>
<li><strong>Zuweisungen berechnen</strong> POST /assignments/compute</li>
<li><strong>Mitarbeiter absolviert</strong> start progress Quiz complete</li>
<li><strong>Zertifikat</strong> POST /certificates/generate/:assignmentId</li>
<li><strong>Audit</strong> GET /audit-log + GET /stats</li>
</ol>
</DevPortalLayout>
)
}

View File

@@ -54,6 +54,7 @@ const navigation: NavItem[] = [
{ title: 'RAG Search API', href: '/api/rag' },
{ title: 'Generation API', href: '/api/generate' },
{ title: 'Export API', href: '/api/export' },
{ title: 'Training API', href: '/api/training' },
],
},
{