package handlers import ( "encoding/json" "net/http" "github.com/breakpilot/ai-compliance-sdk/internal/iace" "github.com/breakpilot/ai-compliance-sdk/internal/rbac" "github.com/gin-gonic/gin" "github.com/google/uuid" ) // ============================================================================ // Mitigations // ============================================================================ // ListProjectMitigations handles GET /projects/:id/mitigations // Returns all mitigations for all hazards in a project. func (h *IACEHandler) ListProjectMitigations(c *gin.Context) { projectID, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"}) return } mitigations, err := h.store.ListMitigationsByProject(c.Request.Context(), projectID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } if mitigations == nil { mitigations = []iace.Mitigation{} } c.JSON(http.StatusOK, gin.H{ "mitigations": mitigations, "total": len(mitigations), }) } // CreateMitigation handles POST /projects/:id/hazards/:hid/mitigations // Creates a new mitigation measure for a hazard. func (h *IACEHandler) CreateMitigation(c *gin.Context) { projectID, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"}) return } hazardID, err := uuid.Parse(c.Param("hid")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid hazard ID"}) return } var req iace.CreateMitigationRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Override hazard ID from URL path req.HazardID = hazardID mitigation, err := h.store.CreateMitigation(c.Request.Context(), req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Update hazard status to mitigated h.store.UpdateHazard(c.Request.Context(), hazardID, map[string]interface{}{ "status": string(iace.HazardStatusMitigated), }) // Audit trail userID := rbac.GetUserID(c) newVals, _ := json.Marshal(mitigation) h.store.AddAuditEntry( c.Request.Context(), projectID, "mitigation", mitigation.ID, iace.AuditActionCreate, userID.String(), nil, newVals, ) c.JSON(http.StatusCreated, gin.H{"mitigation": mitigation}) } // UpdateMitigation handles PUT /mitigations/:mid // Updates a mitigation measure with the provided fields. func (h *IACEHandler) UpdateMitigation(c *gin.Context) { mitigationID, err := uuid.Parse(c.Param("mid")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid mitigation ID"}) return } var updates map[string]interface{} if err := c.ShouldBindJSON(&updates); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } mitigation, err := h.store.UpdateMitigation(c.Request.Context(), mitigationID, updates) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } if mitigation == nil { c.JSON(http.StatusNotFound, gin.H{"error": "mitigation not found"}) return } c.JSON(http.StatusOK, gin.H{"mitigation": mitigation}) } // DeleteMitigation handles DELETE /projects/:id/mitigations/:mid // Deletes a mitigation by ID. func (h *IACEHandler) DeleteMitigation(c *gin.Context) { mitigationID, err := uuid.Parse(c.Param("mid")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid mitigation ID"}) return } if err := h.store.DeleteMitigation(c.Request.Context(), mitigationID); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "mitigation deleted"}) } // VerifyMitigation handles POST /mitigations/:mid/verify // Marks a mitigation as verified with a verification result. func (h *IACEHandler) VerifyMitigation(c *gin.Context) { mitigationID, err := uuid.Parse(c.Param("mid")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid mitigation ID"}) return } var req struct { VerificationResult string `json:"verification_result" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } userID := rbac.GetUserID(c) if err := h.store.VerifyMitigation( c.Request.Context(), mitigationID, req.VerificationResult, userID.String(), ); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "mitigation verified"}) }