This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/admin-v2/ai-compliance-sdk/cmd/server/main.go
BreakPilot Dev ac1bb1d97b
Some checks failed
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
ci/woodpecker/push/integration Pipeline failed
ci/woodpecker/push/main Pipeline failed
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
feat: Implement Compliance Academy E-Learning module (Phases 1-7)
Add complete Academy backend (Go) and frontend (Next.js) for DSGVO/IT-Security/AI-Literacy compliance training:
- Go backend: Course CRUD, enrollments, quiz evaluation, PDF certificates (gofpdf), video generation pipeline (ElevenLabs + HeyGen)
- In-memory data store with PostgreSQL migration for future DB support
- Frontend: Course creation (AI + manual), lesson viewer, interactive quiz, certificate viewer with PDF download
- Fix existing compile errors in generate.go (SearchResult type mismatch), llm/service.go (unused var), rag/service.go (Unicode chars)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 21:18:51 +01:00

198 lines
5.8 KiB
Go

package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/breakpilot/ai-compliance-sdk/internal/api"
"github.com/breakpilot/ai-compliance-sdk/internal/db"
"github.com/breakpilot/ai-compliance-sdk/internal/llm"
"github.com/breakpilot/ai-compliance-sdk/internal/rag"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
)
func main() {
// Load environment variables
if err := godotenv.Load(); err != nil {
log.Println("No .env file found, using environment variables")
}
// Get configuration from environment
port := getEnv("PORT", "8085")
dbURL := getEnv("DATABASE_URL", "postgres://localhost:5432/sdk_states?sslmode=disable")
qdrantURL := getEnv("QDRANT_URL", "http://localhost:6333")
anthropicKey := getEnv("ANTHROPIC_API_KEY", "")
// Initialize database connection
dbPool, err := db.NewPostgresPool(dbURL)
if err != nil {
log.Printf("Warning: Database connection failed: %v", err)
// Continue without database - use in-memory fallback
}
// Initialize RAG service
ragService, err := rag.NewService(qdrantURL)
if err != nil {
log.Printf("Warning: RAG service initialization failed: %v", err)
// Continue without RAG - will return empty results
}
// Initialize LLM service
llmService := llm.NewService(anthropicKey)
// Create Gin router
gin.SetMode(gin.ReleaseMode)
if os.Getenv("GIN_MODE") == "debug" {
gin.SetMode(gin.DebugMode)
}
router := gin.Default()
// CORS middleware
router.Use(corsMiddleware())
// Health check
router.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": "healthy",
"timestamp": time.Now().UTC().Format(time.RFC3339),
"services": gin.H{
"database": dbPool != nil,
"rag": ragService != nil,
"llm": anthropicKey != "",
},
})
})
// API routes
v1 := router.Group("/sdk/v1")
{
// State Management
stateHandler := api.NewStateHandler(dbPool)
v1.GET("/state/:tenantId", stateHandler.GetState)
v1.POST("/state", stateHandler.SaveState)
v1.DELETE("/state/:tenantId", stateHandler.DeleteState)
// RAG Search
ragHandler := api.NewRAGHandler(ragService)
v1.GET("/rag/search", ragHandler.Search)
v1.GET("/rag/status", ragHandler.GetCorpusStatus)
v1.POST("/rag/index", ragHandler.IndexDocument)
// Document Generation
generateHandler := api.NewGenerateHandler(llmService, ragService)
v1.POST("/generate/dsfa", generateHandler.GenerateDSFA)
v1.POST("/generate/tom", generateHandler.GenerateTOM)
v1.POST("/generate/vvt", generateHandler.GenerateVVT)
v1.POST("/generate/gutachten", generateHandler.GenerateGutachten)
// Checkpoint Validation
checkpointHandler := api.NewCheckpointHandler()
v1.GET("/checkpoints", checkpointHandler.GetAll)
v1.POST("/checkpoints/validate", checkpointHandler.Validate)
// Academy (Compliance E-Learning)
academyHandler := api.NewAcademyHandler(dbPool, llmService, ragService)
academy := v1.Group("/academy")
{
// Course CRUD
academy.GET("/courses", academyHandler.ListCourses)
academy.GET("/courses/:id", academyHandler.GetCourse)
academy.POST("/courses", academyHandler.CreateCourse)
academy.PUT("/courses/:id", academyHandler.UpdateCourse)
academy.DELETE("/courses/:id", academyHandler.DeleteCourse)
// Statistics
academy.GET("/statistics", academyHandler.GetStatistics)
// Enrollments
academy.GET("/enrollments", academyHandler.ListEnrollments)
academy.POST("/enrollments", academyHandler.EnrollUser)
academy.PUT("/enrollments/:id/progress", academyHandler.UpdateProgress)
academy.POST("/enrollments/:id/complete", academyHandler.CompleteEnrollment)
// Quiz
academy.POST("/lessons/:id/quiz", academyHandler.SubmitQuiz)
// Certificates
academy.POST("/enrollments/:id/certificate", academyHandler.GenerateCertificateEndpoint)
academy.GET("/certificates/:id", academyHandler.GetCertificate)
academy.GET("/certificates/:id/pdf", academyHandler.DownloadCertificatePDF)
// AI Course Generation
academy.POST("/courses/generate", academyHandler.GenerateCourse)
academy.POST("/lessons/:id/regenerate", academyHandler.RegenerateLesson)
// Video Generation
academy.POST("/courses/:id/generate-videos", academyHandler.GenerateVideos)
academy.GET("/courses/:id/video-status", academyHandler.GetVideoStatus)
}
}
// Create server
srv := &http.Server{
Addr: ":" + port,
Handler: router,
}
// Graceful shutdown
go func() {
log.Printf("SDK Backend starting on port %s", port)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("Failed to start server: %v", err)
}
}()
// Wait for interrupt signal
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down server...")
// Give outstanding requests 5 seconds to complete
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server forced to shutdown:", err)
}
// Close database connection
if dbPool != nil {
dbPool.Close()
}
log.Println("Server exited")
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
func corsMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With, If-Match, If-None-Match")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
c.Writer.Header().Set("Access-Control-Expose-Headers", "ETag, Last-Modified")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}