package handlers import ( "net/http" "github.com/breakpilot/ai-compliance-sdk/internal/gci" "github.com/breakpilot/ai-compliance-sdk/internal/rbac" "github.com/gin-gonic/gin" ) type GCIHandlers struct { engine *gci.Engine } func NewGCIHandlers(engine *gci.Engine) *GCIHandlers { return &GCIHandlers{engine: engine} } // GetScore returns the GCI score for the current tenant // GET /sdk/v1/gci/score func (h *GCIHandlers) GetScore(c *gin.Context) { tenantID := rbac.GetTenantID(c).String() profile := c.DefaultQuery("profile", "default") result := h.engine.Calculate(tenantID, profile) c.JSON(http.StatusOK, result) } // GetScoreBreakdown returns the detailed 4-level GCI breakdown // GET /sdk/v1/gci/score/breakdown func (h *GCIHandlers) GetScoreBreakdown(c *gin.Context) { tenantID := rbac.GetTenantID(c).String() profile := c.DefaultQuery("profile", "default") breakdown := h.engine.CalculateBreakdown(tenantID, profile) c.JSON(http.StatusOK, breakdown) } // GetHistory returns historical GCI snapshots for trend analysis // GET /sdk/v1/gci/score/history func (h *GCIHandlers) GetHistory(c *gin.Context) { tenantID := rbac.GetTenantID(c).String() history := h.engine.GetHistory(tenantID) c.JSON(http.StatusOK, gin.H{ "tenant_id": tenantID, "snapshots": history, "total": len(history), }) } // GetMatrix returns the compliance matrix (roles x regulations) // GET /sdk/v1/gci/matrix func (h *GCIHandlers) GetMatrix(c *gin.Context) { tenantID := rbac.GetTenantID(c).String() matrix := h.engine.GetMatrix(tenantID) c.JSON(http.StatusOK, gin.H{ "tenant_id": tenantID, "matrix": matrix, }) } // GetAuditTrail returns the audit trail for the latest GCI calculation // GET /sdk/v1/gci/audit-trail func (h *GCIHandlers) GetAuditTrail(c *gin.Context) { tenantID := rbac.GetTenantID(c).String() profile := c.DefaultQuery("profile", "default") result := h.engine.Calculate(tenantID, profile) c.JSON(http.StatusOK, gin.H{ "tenant_id": tenantID, "gci_score": result.GCIScore, "audit_trail": result.AuditTrail, }) } // GetNIS2Score returns the NIS2-specific compliance score // GET /sdk/v1/gci/nis2/score func (h *GCIHandlers) GetNIS2Score(c *gin.Context) { tenantID := rbac.GetTenantID(c).String() score := gci.CalculateNIS2Score(tenantID) c.JSON(http.StatusOK, score) } // ListNIS2Roles returns available NIS2 responsibility roles // GET /sdk/v1/gci/nis2/roles func (h *GCIHandlers) ListNIS2Roles(c *gin.Context) { roles := gci.ListNIS2Roles() c.JSON(http.StatusOK, gin.H{ "roles": roles, "total": len(roles), }) } // AssignNIS2Role assigns a NIS2 role to a user (stub - returns mock) // POST /sdk/v1/gci/nis2/roles/assign func (h *GCIHandlers) AssignNIS2Role(c *gin.Context) { var req struct { RoleID string `json:"role_id" binding:"required"` UserID string `json:"user_id" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } role, found := gci.GetNIS2Role(req.RoleID) if !found { c.JSON(http.StatusNotFound, gin.H{"error": "NIS2 role not found"}) return } c.JSON(http.StatusOK, gin.H{ "status": "assigned", "role": role, "user_id": req.UserID, }) } // GetISOGapAnalysis returns the ISO 27001 gap analysis // GET /sdk/v1/gci/iso/gap-analysis func (h *GCIHandlers) GetISOGapAnalysis(c *gin.Context) { tenantID := rbac.GetTenantID(c).String() analysis := gci.CalculateISOGapAnalysis(tenantID) c.JSON(http.StatusOK, analysis) } // ListISOMappings returns all ISO 27001 control mappings // GET /sdk/v1/gci/iso/mappings func (h *GCIHandlers) ListISOMappings(c *gin.Context) { category := c.Query("category") if category != "" { controls := gci.GetISOControlsByCategory(category) c.JSON(http.StatusOK, gin.H{ "controls": controls, "total": len(controls), "category": category, }) return } categories := []string{"A.5", "A.6", "A.7", "A.8"} result := make(map[string][]gci.ISOControl) total := 0 for _, cat := range categories { controls := gci.GetISOControlsByCategory(cat) if len(controls) > 0 { result[cat] = controls total += len(controls) } } c.JSON(http.StatusOK, gin.H{ "categories": result, "total": total, }) } // GetISOMapping returns a single ISO control by ID // GET /sdk/v1/gci/iso/mappings/:controlId func (h *GCIHandlers) GetISOMapping(c *gin.Context) { controlID := c.Param("controlId") control, found := gci.GetISOControlByID(controlID) if !found { c.JSON(http.StatusNotFound, gin.H{"error": "ISO control not found"}) return } c.JSON(http.StatusOK, control) } // GetWeightProfiles returns available weighting profiles // GET /sdk/v1/gci/profiles func (h *GCIHandlers) GetWeightProfiles(c *gin.Context) { profiles := []string{"default", "nis2_relevant", "ki_nutzer"} result := make([]gci.WeightProfile, 0, len(profiles)) for _, id := range profiles { result = append(result, gci.GetProfile(id)) } c.JSON(http.StatusOK, gin.H{ "profiles": result, }) }