package handlers import ( "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/breakpilot/ai-compliance-sdk/internal/rbac" "github.com/breakpilot/ai-compliance-sdk/internal/ucca" ) // GetByRegulation returns obligations grouped by regulation // GET /sdk/v1/ucca/obligations/:assessmentId/by-regulation func (h *ObligationsHandlers) GetByRegulation(c *gin.Context) { tenantID := rbac.GetTenantID(c) assessmentID := c.Param("assessmentId") if h.store == nil { c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"}) return } id, err := uuid.Parse(assessmentID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"}) return } assessment, err := h.store.GetAssessment(c.Request.Context(), tenantID, id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Assessment not found"}) return } grouped := h.registry.GroupByRegulation(assessment.Overview.Obligations) c.JSON(http.StatusOK, ucca.ObligationsByRegulationResponse{ Regulations: grouped, }) } // GetByDeadline returns obligations grouped by deadline timeframe // GET /sdk/v1/ucca/obligations/:assessmentId/by-deadline func (h *ObligationsHandlers) GetByDeadline(c *gin.Context) { tenantID := rbac.GetTenantID(c) assessmentID := c.Param("assessmentId") if h.store == nil { c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"}) return } id, err := uuid.Parse(assessmentID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"}) return } assessment, err := h.store.GetAssessment(c.Request.Context(), tenantID, id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Assessment not found"}) return } grouped := h.registry.GroupByDeadline(assessment.Overview.Obligations) c.JSON(http.StatusOK, grouped) } // GetByResponsible returns obligations grouped by responsible role // GET /sdk/v1/ucca/obligations/:assessmentId/by-responsible func (h *ObligationsHandlers) GetByResponsible(c *gin.Context) { tenantID := rbac.GetTenantID(c) assessmentID := c.Param("assessmentId") if h.store == nil { c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"}) return } id, err := uuid.Parse(assessmentID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"}) return } assessment, err := h.store.GetAssessment(c.Request.Context(), tenantID, id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Assessment not found"}) return } grouped := h.registry.GroupByResponsible(assessment.Overview.Obligations) c.JSON(http.StatusOK, ucca.ObligationsByResponsibleResponse{ ByRole: grouped, }) } // ListRegulations returns all available regulation modules // GET /sdk/v1/ucca/obligations/regulations func (h *ObligationsHandlers) ListRegulations(c *gin.Context) { modules := h.registry.ListModules() c.JSON(http.StatusOK, ucca.AvailableRegulationsResponse{ Regulations: modules, }) } // GetDecisionTree returns the decision tree for a specific regulation // GET /sdk/v1/ucca/obligations/regulations/:regulationId/decision-tree func (h *ObligationsHandlers) GetDecisionTree(c *gin.Context) { regulationID := c.Param("regulationId") tree, err := h.registry.GetDecisionTree(regulationID) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, tree) } // GetTOMControlsForObligation returns TOM controls linked to an obligation // GET /sdk/v1/ucca/obligations/:id/tom-controls func (h *ObligationsHandlers) GetTOMControlsForObligation(c *gin.Context) { obligationID := c.Param("obligationId") if h.tomMapper == nil { c.JSON(http.StatusNotImplemented, gin.H{"error": "TOM mapping not available"}) return } controls := h.tomMapper.GetControlsForObligation(obligationID) controlIDs := h.tomMapper.GetControlIDsForObligation(obligationID) c.JSON(http.StatusOK, gin.H{ "obligation_id": obligationID, "control_ids": controlIDs, "controls": controls, "count": len(controls), }) } // GapAnalysis performs a TOM control gap analysis // POST /sdk/v1/ucca/obligations/gap-analysis func (h *ObligationsHandlers) GapAnalysis(c *gin.Context) { if h.gapAnalyzer == nil { c.JSON(http.StatusNotImplemented, gin.H{"error": "Gap analysis not available"}) return } var req ucca.GapAnalysisRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()}) return } result := h.gapAnalyzer.Analyze(&req) c.JSON(http.StatusOK, result) } // GetObligationsForControl returns obligations linked to a TOM control // GET /sdk/v1/ucca/obligations/tom-controls/:controlId/obligations func (h *ObligationsHandlers) GetObligationsForControl(c *gin.Context) { controlID := c.Param("controlId") if h.tomMapper == nil { c.JSON(http.StatusNotImplemented, gin.H{"error": "TOM mapping not available"}) return } obligationIDs := h.tomMapper.GetObligationsForControl(controlID) var control *ucca.TOMControl if h.tomIndex != nil { control, _ = h.tomIndex.GetControl(controlID) } c.JSON(http.StatusOK, gin.H{ "control_id": controlID, "control": control, "obligation_ids": obligationIDs, "count": len(obligationIDs), }) }