feat: Add Academy, Whistleblower, Incidents, Vendor, DSB, SSO, Reporting, Multi-Tenant and Industry backends

Go handlers, models, stores and migrations for all SDK modules.
Updates developer portal navigation and BYOEH page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-13 21:11:27 +01:00
parent 364d2c69ff
commit 504dd3591b
40 changed files with 13105 additions and 7 deletions

View File

@@ -15,8 +15,16 @@ import (
"github.com/breakpilot/ai-compliance-sdk/internal/dsgvo"
"github.com/breakpilot/ai-compliance-sdk/internal/llm"
"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
"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/ucca"
"github.com/breakpilot/ai-compliance-sdk/internal/whistleblower"
"github.com/breakpilot/ai-compliance-sdk/internal/dsb"
"github.com/breakpilot/ai-compliance-sdk/internal/multitenant"
"github.com/breakpilot/ai-compliance-sdk/internal/reporting"
"github.com/breakpilot/ai-compliance-sdk/internal/sso"
"github.com/breakpilot/ai-compliance-sdk/internal/vendor"
"github.com/breakpilot/ai-compliance-sdk/internal/workshop"
"github.com/breakpilot/ai-compliance-sdk/internal/portfolio"
"github.com/gin-contrib/cors"
@@ -59,6 +67,14 @@ func main() {
roadmapStore := roadmap.NewStore(pool)
workshopStore := workshop.NewStore(pool)
portfolioStore := portfolio.NewStore(pool)
academyStore := academy.NewStore(pool)
whistleblowerStore := whistleblower.NewStore(pool)
incidentStore := incidents.NewStore(pool)
vendorStore := vendor.NewStore(pool)
reportingStore := reporting.NewStore(pool, dsgvoStore, vendorStore, incidentStore, whistleblowerStore, academyStore)
ssoStore := sso.NewStore(pool)
multitenantStore := multitenant.NewStore(pool, rbacStore, reportingStore)
dsbStore := dsb.NewStore(pool, reportingStore)
// Initialize services
rbacService := rbac.NewService(rbacStore)
@@ -98,6 +114,15 @@ func main() {
workshopHandlers := handlers.NewWorkshopHandlers(workshopStore)
portfolioHandlers := handlers.NewPortfolioHandlers(portfolioStore)
draftingHandlers := handlers.NewDraftingHandlers(accessGate, providerRegistry, piiDetector, auditStore, trailBuilder)
academyHandlers := handlers.NewAcademyHandlers(academyStore)
whistleblowerHandlers := handlers.NewWhistleblowerHandlers(whistleblowerStore)
incidentHandlers := handlers.NewIncidentHandlers(incidentStore)
vendorHandlers := handlers.NewVendorHandlers(vendorStore)
reportingHandlers := handlers.NewReportingHandlers(reportingStore)
ssoHandlers := handlers.NewSSOHandlers(ssoStore, cfg.JWTSecret)
multitenantHandlers := handlers.NewMultiTenantHandlers(multitenantStore, rbacStore)
industryHandlers := handlers.NewIndustryHandlers()
dsbHandlers := handlers.NewDSBHandlers(dsbStore)
// Initialize middleware
rbacMiddleware := rbac.NewMiddleware(rbacService, policyEngine)
@@ -435,6 +460,197 @@ func main() {
draftingRoutes.POST("/validate", draftingHandlers.ValidateDocument)
draftingRoutes.GET("/history", draftingHandlers.GetDraftHistory)
}
// Academy routes - E-Learning / Compliance Training
academyRoutes := v1.Group("/academy")
{
// Courses
academyRoutes.POST("/courses", academyHandlers.CreateCourse)
academyRoutes.GET("/courses", academyHandlers.ListCourses)
academyRoutes.GET("/courses/:id", academyHandlers.GetCourse)
academyRoutes.PUT("/courses/:id", academyHandlers.UpdateCourse)
academyRoutes.DELETE("/courses/:id", academyHandlers.DeleteCourse)
// Enrollments
academyRoutes.POST("/enrollments", academyHandlers.CreateEnrollment)
academyRoutes.GET("/enrollments", academyHandlers.ListEnrollments)
academyRoutes.PUT("/enrollments/:id/progress", academyHandlers.UpdateProgress)
academyRoutes.POST("/enrollments/:id/complete", academyHandlers.CompleteEnrollment)
// Certificates
academyRoutes.GET("/certificates/:id", academyHandlers.GetCertificate)
academyRoutes.POST("/enrollments/:id/certificate", academyHandlers.GenerateCertificate)
// Quiz
academyRoutes.POST("/courses/:id/quiz", academyHandlers.SubmitQuiz)
// Statistics
academyRoutes.GET("/stats", academyHandlers.GetStatistics)
}
// Whistleblower routes - Hinweisgebersystem (HinSchG)
whistleblowerRoutes := v1.Group("/whistleblower")
{
// Public endpoints (anonymous reporting)
whistleblowerRoutes.POST("/reports/submit", whistleblowerHandlers.SubmitReport)
whistleblowerRoutes.GET("/reports/access/:accessKey", whistleblowerHandlers.GetReportByAccessKey)
whistleblowerRoutes.POST("/reports/access/:accessKey/messages", whistleblowerHandlers.SendPublicMessage)
// Admin endpoints
whistleblowerRoutes.GET("/reports", whistleblowerHandlers.ListReports)
whistleblowerRoutes.GET("/reports/:id", whistleblowerHandlers.GetReport)
whistleblowerRoutes.PUT("/reports/:id", whistleblowerHandlers.UpdateReport)
whistleblowerRoutes.DELETE("/reports/:id", whistleblowerHandlers.DeleteReport)
whistleblowerRoutes.POST("/reports/:id/acknowledge", whistleblowerHandlers.AcknowledgeReport)
whistleblowerRoutes.POST("/reports/:id/investigate", whistleblowerHandlers.StartInvestigation)
whistleblowerRoutes.POST("/reports/:id/measures", whistleblowerHandlers.AddMeasure)
whistleblowerRoutes.POST("/reports/:id/close", whistleblowerHandlers.CloseReport)
whistleblowerRoutes.POST("/reports/:id/messages", whistleblowerHandlers.SendAdminMessage)
whistleblowerRoutes.GET("/reports/:id/messages", whistleblowerHandlers.ListMessages)
// Statistics
whistleblowerRoutes.GET("/stats", whistleblowerHandlers.GetStatistics)
}
// Incidents routes - Datenpannen-Management (DSGVO Art. 33/34)
incidentRoutes := v1.Group("/incidents")
{
// Incident CRUD
incidentRoutes.POST("", incidentHandlers.CreateIncident)
incidentRoutes.GET("", incidentHandlers.ListIncidents)
incidentRoutes.GET("/:id", incidentHandlers.GetIncident)
incidentRoutes.PUT("/:id", incidentHandlers.UpdateIncident)
incidentRoutes.DELETE("/:id", incidentHandlers.DeleteIncident)
// Risk Assessment
incidentRoutes.POST("/:id/assess-risk", incidentHandlers.AssessRisk)
// Authority Notification (Art. 33)
incidentRoutes.POST("/:id/notify-authority", incidentHandlers.SubmitAuthorityNotification)
// Data Subject Notification (Art. 34)
incidentRoutes.POST("/:id/notify-subjects", incidentHandlers.NotifyDataSubjects)
// Measures
incidentRoutes.POST("/:id/measures", incidentHandlers.AddMeasure)
incidentRoutes.PUT("/:id/measures/:measureId", incidentHandlers.UpdateMeasure)
incidentRoutes.POST("/:id/measures/:measureId/complete", incidentHandlers.CompleteMeasure)
// Timeline
incidentRoutes.POST("/:id/timeline", incidentHandlers.AddTimelineEntry)
// Lifecycle
incidentRoutes.POST("/:id/close", incidentHandlers.CloseIncident)
// Statistics
incidentRoutes.GET("/stats", incidentHandlers.GetStatistics)
}
// Vendor Compliance routes - Vendor Management & AVV/DPA (DSGVO Art. 28)
vendorRoutes := v1.Group("/vendors")
{
// Vendor CRUD
vendorRoutes.POST("", vendorHandlers.CreateVendor)
vendorRoutes.GET("", vendorHandlers.ListVendors)
vendorRoutes.GET("/:id", vendorHandlers.GetVendor)
vendorRoutes.PUT("/:id", vendorHandlers.UpdateVendor)
vendorRoutes.DELETE("/:id", vendorHandlers.DeleteVendor)
// Contracts (AVV/DPA)
vendorRoutes.POST("/contracts", vendorHandlers.CreateContract)
vendorRoutes.GET("/contracts", vendorHandlers.ListContracts)
vendorRoutes.GET("/contracts/:id", vendorHandlers.GetContract)
vendorRoutes.PUT("/contracts/:id", vendorHandlers.UpdateContract)
vendorRoutes.DELETE("/contracts/:id", vendorHandlers.DeleteContract)
// Findings
vendorRoutes.POST("/findings", vendorHandlers.CreateFinding)
vendorRoutes.GET("/findings", vendorHandlers.ListFindings)
vendorRoutes.GET("/findings/:id", vendorHandlers.GetFinding)
vendorRoutes.PUT("/findings/:id", vendorHandlers.UpdateFinding)
vendorRoutes.POST("/findings/:id/resolve", vendorHandlers.ResolveFinding)
// Control Instances
vendorRoutes.POST("/controls", vendorHandlers.UpsertControlInstance)
vendorRoutes.GET("/controls", vendorHandlers.ListControlInstances)
// Templates
vendorRoutes.GET("/templates", vendorHandlers.ListTemplates)
vendorRoutes.GET("/templates/:templateId", vendorHandlers.GetTemplate)
vendorRoutes.POST("/templates", vendorHandlers.CreateTemplate)
vendorRoutes.POST("/templates/:templateId/apply", vendorHandlers.ApplyTemplate)
// Statistics
vendorRoutes.GET("/stats", vendorHandlers.GetStatistics)
}
// Reporting routes - Executive Compliance Reporting Dashboard
reportingRoutes := v1.Group("/reporting")
{
reportingRoutes.GET("/executive", reportingHandlers.GetExecutiveReport)
reportingRoutes.GET("/score", reportingHandlers.GetComplianceScore)
reportingRoutes.GET("/deadlines", reportingHandlers.GetUpcomingDeadlines)
reportingRoutes.GET("/risks", reportingHandlers.GetRiskOverview)
}
// SSO routes - Single Sign-On (SAML/OIDC)
ssoRoutes := v1.Group("/sso")
{
// Config CRUD
ssoRoutes.POST("/configs", ssoHandlers.CreateConfig)
ssoRoutes.GET("/configs", ssoHandlers.ListConfigs)
ssoRoutes.GET("/configs/:id", ssoHandlers.GetConfig)
ssoRoutes.PUT("/configs/:id", ssoHandlers.UpdateConfig)
ssoRoutes.DELETE("/configs/:id", ssoHandlers.DeleteConfig)
// SSO Users
ssoRoutes.GET("/users", ssoHandlers.ListUsers)
// OIDC Flow
ssoRoutes.GET("/oidc/login", ssoHandlers.InitiateOIDCLogin)
ssoRoutes.GET("/oidc/callback", ssoHandlers.HandleOIDCCallback)
}
// Multi-Tenant Administration routes
mtRoutes := v1.Group("/multi-tenant")
{
mtRoutes.GET("/overview", multitenantHandlers.GetOverview)
mtRoutes.POST("/tenants", multitenantHandlers.CreateTenant)
mtRoutes.GET("/tenants/:id", multitenantHandlers.GetTenantDetail)
mtRoutes.PUT("/tenants/:id", multitenantHandlers.UpdateTenant)
mtRoutes.GET("/tenants/:id/namespaces", multitenantHandlers.ListNamespaces)
mtRoutes.POST("/tenants/:id/namespaces", multitenantHandlers.CreateNamespace)
mtRoutes.POST("/switch", multitenantHandlers.SwitchTenant)
}
// Industry-Specific Templates routes (Phase 3.3)
industryRoutes := v1.Group("/industry/templates")
{
industryRoutes.GET("", industryHandlers.ListIndustries)
industryRoutes.GET("/:slug", industryHandlers.GetIndustry)
industryRoutes.GET("/:slug/vvt", industryHandlers.GetVVTTemplates)
industryRoutes.GET("/:slug/tom", industryHandlers.GetTOMRecommendations)
industryRoutes.GET("/:slug/risks", industryHandlers.GetRiskScenarios)
}
// DSB-as-a-Service Portal routes (Phase 3.4)
dsbRoutes := v1.Group("/dsb")
{
dsbRoutes.GET("/dashboard", dsbHandlers.GetDashboard)
dsbRoutes.POST("/assignments", dsbHandlers.CreateAssignment)
dsbRoutes.GET("/assignments", dsbHandlers.ListAssignments)
dsbRoutes.GET("/assignments/:id", dsbHandlers.GetAssignment)
dsbRoutes.PUT("/assignments/:id", dsbHandlers.UpdateAssignment)
dsbRoutes.POST("/assignments/:id/hours", dsbHandlers.CreateHourEntry)
dsbRoutes.GET("/assignments/:id/hours", dsbHandlers.ListHours)
dsbRoutes.GET("/assignments/:id/hours/summary", dsbHandlers.GetHoursSummary)
dsbRoutes.POST("/assignments/:id/tasks", dsbHandlers.CreateTask)
dsbRoutes.GET("/assignments/:id/tasks", dsbHandlers.ListTasks)
dsbRoutes.PUT("/tasks/:taskId", dsbHandlers.UpdateTask)
dsbRoutes.POST("/tasks/:taskId/complete", dsbHandlers.CompleteTask)
dsbRoutes.POST("/assignments/:id/communications", dsbHandlers.CreateCommunication)
dsbRoutes.GET("/assignments/:id/communications", dsbHandlers.ListCommunications)
}
}
// Create HTTP server