From e5cb5e37ada5e0dcfc1c2fd2adca260a868865b2 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Thu, 26 Feb 2026 09:46:16 +0100 Subject: [PATCH] feat(training): register training routes and add missing academy API functions Connect the existing training engine handlers (40+ endpoints) to the router in main.go. This was the critical blocker preventing the training content pipeline from being accessible. Also adds generateCourse, generateVideos, and getVideoStatus functions to the academy API client, plus the GenerateCourseRequest type. Co-Authored-By: Claude Opus 4.6 --- admin-compliance/lib/sdk/academy/api.ts | 47 +++++++++++++++++ admin-compliance/lib/sdk/academy/types.ts | 9 ++++ ai-compliance-sdk/cmd/server/main.go | 64 +++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/admin-compliance/lib/sdk/academy/api.ts b/admin-compliance/lib/sdk/academy/api.ts index 46e259e..c9b90f4 100644 --- a/admin-compliance/lib/sdk/academy/api.ts +++ b/admin-compliance/lib/sdk/academy/api.ts @@ -10,6 +10,7 @@ import { CourseCategory, CourseCreateRequest, CourseUpdateRequest, + GenerateCourseRequest, Enrollment, EnrollmentStatus, EnrollmentListResponse, @@ -273,6 +274,52 @@ export async function fetchAcademyStatistics(): Promise { ) } +// ============================================================================= +// COURSE GENERATION (via Training Engine) +// ============================================================================= + +/** + * KI-gestuetzten Kurs generieren (nutzt intern Training Content Pipeline) + */ +export async function generateCourse(request: GenerateCourseRequest): Promise { + return fetchWithTimeout( + `${ACADEMY_API_BASE}/courses/generate`, + { + method: 'POST', + body: JSON.stringify(request) + }, + 120000 // 2 min timeout for LLM generation + ) +} + +/** + * Videos fuer alle Lektionen eines Kurses generieren + */ +export async function generateVideos(courseId: string): Promise<{ status: string; jobId?: string }> { + return fetchWithTimeout<{ status: string; jobId?: string }>( + `${ACADEMY_API_BASE}/courses/${courseId}/generate-videos`, + { + method: 'POST' + }, + 300000 // 5 min timeout for video generation + ) +} + +/** + * Video-Generierungsstatus abrufen + */ +export async function getVideoStatus(courseId: string): Promise<{ + status: string + total: number + completed: number + failed: number + videos: Array<{ lessonId: string; status: string; url?: string }> +}> { + return fetchWithTimeout( + `${ACADEMY_API_BASE}/courses/${courseId}/video-status` + ) +} + // ============================================================================= // SDK PROXY FUNCTION (wraps fetchCourses + fetchAcademyStatistics) // ============================================================================= diff --git a/admin-compliance/lib/sdk/academy/types.ts b/admin-compliance/lib/sdk/academy/types.ts index 2a09fc4..a9d7317 100644 --- a/admin-compliance/lib/sdk/academy/types.ts +++ b/admin-compliance/lib/sdk/academy/types.ts @@ -215,6 +215,15 @@ export interface CourseUpdateRequest { requiredForRoles?: string[] } +export interface GenerateCourseRequest { + title: string + category: CourseCategory + description?: string + regulationArea?: string + language?: string + durationMinutes?: number +} + export interface EnrollUserRequest { courseId: string userId: string diff --git a/ai-compliance-sdk/cmd/server/main.go b/ai-compliance-sdk/cmd/server/main.go index 54923ef..66254c3 100644 --- a/ai-compliance-sdk/cmd/server/main.go +++ b/ai-compliance-sdk/cmd/server/main.go @@ -18,6 +18,7 @@ import ( "github.com/breakpilot/ai-compliance-sdk/internal/academy" "github.com/breakpilot/ai-compliance-sdk/internal/incidents" "github.com/breakpilot/ai-compliance-sdk/internal/roadmap" + "github.com/breakpilot/ai-compliance-sdk/internal/training" "github.com/breakpilot/ai-compliance-sdk/internal/ucca" "github.com/breakpilot/ai-compliance-sdk/internal/whistleblower" "github.com/breakpilot/ai-compliance-sdk/internal/iace" @@ -69,6 +70,7 @@ func main() { incidentStore := incidents.NewStore(pool) vendorStore := vendor.NewStore(pool) iaceStore := iace.NewStore(pool) + trainingStore := training.NewStore(pool) // Initialize services rbacService := rbac.NewService(rbacStore) @@ -90,6 +92,10 @@ func main() { // Initialize PII detector piiDetector := llm.NewPIIDetectorWithPatterns(llm.AllPIIPatterns()) + // Initialize TTS client and content generator for training + ttsClient := training.NewTTSClient(cfg.TTSServiceURL) + contentGenerator := training.NewContentGenerator(providerRegistry, piiDetector, trainingStore, ttsClient) + // Initialize access gate accessGate := llm.NewAccessGate(policyEngine, piiDetector, providerRegistry) @@ -113,6 +119,7 @@ func main() { incidentHandlers := handlers.NewIncidentHandlers(incidentStore) vendorHandlers := handlers.NewVendorHandlers(vendorStore) iaceHandler := handlers.NewIACEHandler(iaceStore) + trainingHandlers := handlers.NewTrainingHandlers(trainingStore, contentGenerator) // Initialize middleware rbacMiddleware := rbac.NewMiddleware(rbacService, policyEngine) @@ -478,6 +485,63 @@ func main() { academyRoutes.GET("/stats", academyHandlers.GetStatistics) } + // Training Engine routes - Compliance Training Content Pipeline + trainingRoutes := v1.Group("/training") + { + // Module CRUD + trainingRoutes.GET("/modules", trainingHandlers.ListModules) + trainingRoutes.GET("/modules/:id", trainingHandlers.GetModule) + trainingRoutes.POST("/modules", trainingHandlers.CreateModule) + trainingRoutes.PUT("/modules/:id", trainingHandlers.UpdateModule) + + // Compliance Training Matrix (CTM) + trainingRoutes.GET("/matrix", trainingHandlers.GetMatrix) + trainingRoutes.GET("/matrix/:role", trainingHandlers.GetMatrixForRole) + trainingRoutes.POST("/matrix", trainingHandlers.SetMatrixEntry) + trainingRoutes.DELETE("/matrix/:role/:moduleId", trainingHandlers.DeleteMatrixEntry) + + // Assignments + trainingRoutes.POST("/assignments/compute", trainingHandlers.ComputeAssignments) + trainingRoutes.GET("/assignments", trainingHandlers.ListAssignments) + trainingRoutes.GET("/assignments/:id", trainingHandlers.GetAssignment) + trainingRoutes.POST("/assignments/:id/start", trainingHandlers.StartAssignment) + trainingRoutes.POST("/assignments/:id/progress", trainingHandlers.UpdateAssignmentProgress) + trainingRoutes.POST("/assignments/:id/complete", trainingHandlers.CompleteAssignment) + + // Quiz + trainingRoutes.GET("/quiz/:moduleId", trainingHandlers.GetQuiz) + trainingRoutes.POST("/quiz/:moduleId/submit", trainingHandlers.SubmitQuiz) + trainingRoutes.GET("/quiz/attempts/:assignmentId", trainingHandlers.GetQuizAttempts) + + // Content Generation (LLM) + trainingRoutes.POST("/content/generate", trainingHandlers.GenerateContent) + trainingRoutes.POST("/content/generate-quiz", trainingHandlers.GenerateQuiz) + trainingRoutes.POST("/content/generate-all", trainingHandlers.GenerateAllContent) + trainingRoutes.POST("/content/generate-all-quiz", trainingHandlers.GenerateAllQuizzes) + trainingRoutes.GET("/content/:moduleId", trainingHandlers.GetContent) + trainingRoutes.POST("/content/:id/publish", trainingHandlers.PublishContent) + + // Media (Audio/Video via TTS Service) + trainingRoutes.POST("/content/:moduleId/generate-audio", trainingHandlers.GenerateAudio) + trainingRoutes.POST("/content/:moduleId/generate-video", trainingHandlers.GenerateVideo) + trainingRoutes.POST("/content/:moduleId/preview-script", trainingHandlers.PreviewVideoScript) + trainingRoutes.GET("/media/module/:moduleId", trainingHandlers.GetModuleMedia) + trainingRoutes.GET("/media/:id/url", trainingHandlers.GetMediaURL) + trainingRoutes.POST("/media/:id/publish", trainingHandlers.PublishMedia) + + // Deadlines & Escalation + trainingRoutes.GET("/deadlines", trainingHandlers.GetDeadlines) + trainingRoutes.GET("/deadlines/overdue", trainingHandlers.GetOverdueDeadlines) + trainingRoutes.POST("/escalation/check", trainingHandlers.CheckEscalation) + + // Audit & Statistics + trainingRoutes.GET("/audit-log", trainingHandlers.GetAuditLog) + trainingRoutes.GET("/stats", trainingHandlers.GetStats) + + // Certificates + trainingRoutes.GET("/certificates/:id/verify", trainingHandlers.VerifyCertificate) + } + // Whistleblower routes - Hinweisgebersystem (HinSchG) whistleblowerRoutes := v1.Group("/whistleblower") {