Files
breakpilot-compliance/ai-compliance-sdk/internal/api/handlers/training_handlers_matrix.go
Sharang Parnerkar 3f306fb6f0 refactor(go/handlers): split iace_handler and training_handlers into focused files
iace_handler.go (2706 LOC) split into 9 files:
- iace_handler.go: struct, constructor, shared helpers (~156 LOC)
- iace_handler_projects.go: project CRUD + InitFromProfile (~310 LOC)
- iace_handler_components.go: components + classification (~387 LOC)
- iace_handler_hazards.go: hazard library, CRUD, risk assessment (~469 LOC)
- iace_handler_mitigations.go: mitigations, evidence, verification plans (~293 LOC)
- iace_handler_techfile.go: CE tech file generation/export (~452 LOC)
- iace_handler_monitoring.go: monitoring events + audit trail (~134 LOC)
- iace_handler_refdata.go: ISO 12100 ref data, patterns, suggestions (~465 LOC)
- iace_handler_rag.go: RAG library search + section enrichment (~142 LOC)

training_handlers.go (1864 LOC) split into 9 files:
- training_handlers.go: struct + constructor (~23 LOC)
- training_handlers_modules.go: module CRUD (~226 LOC)
- training_handlers_matrix.go: CTM matrix endpoints (~95 LOC)
- training_handlers_assignments.go: assignment lifecycle (~243 LOC)
- training_handlers_quiz.go: quiz submit/grade/attempts (~185 LOC)
- training_handlers_content.go: LLM content/audio/video generation (~274 LOC)
- training_handlers_media.go: media, streaming, interactive video (~325 LOC)
- training_handlers_blocks.go: block configs + canonical controls (~280 LOC)
- training_handlers_stats.go: deadlines, escalation, audit, certificates (~290 LOC)

All files remain in package handlers. Zero behavior changes. All exported
function names preserved. All files under 500 LOC hard cap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 09:17:20 +02:00

96 lines
2.6 KiB
Go

package handlers
import (
"net/http"
"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
"github.com/breakpilot/ai-compliance-sdk/internal/training"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
// ============================================================================
// Matrix Endpoints
// ============================================================================
// GetMatrix returns the full CTM for the tenant
// GET /sdk/v1/training/matrix
func (h *TrainingHandlers) GetMatrix(c *gin.Context) {
tenantID := rbac.GetTenantID(c)
entries, err := h.store.GetMatrixForTenant(c.Request.Context(), tenantID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
resp := training.BuildMatrixResponse(entries)
c.JSON(http.StatusOK, resp)
}
// GetMatrixForRole returns matrix entries for a specific role
// GET /sdk/v1/training/matrix/:role
func (h *TrainingHandlers) GetMatrixForRole(c *gin.Context) {
tenantID := rbac.GetTenantID(c)
role := c.Param("role")
entries, err := h.store.GetMatrixForRole(c.Request.Context(), tenantID, role)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"role": role,
"label": training.RoleLabels[role],
"entries": entries,
"total": len(entries),
})
}
// SetMatrixEntry creates or updates a CTM entry
// POST /sdk/v1/training/matrix
func (h *TrainingHandlers) SetMatrixEntry(c *gin.Context) {
tenantID := rbac.GetTenantID(c)
var req training.SetMatrixEntryRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
entry := &training.TrainingMatrixEntry{
TenantID: tenantID,
RoleCode: req.RoleCode,
ModuleID: req.ModuleID,
IsMandatory: req.IsMandatory,
Priority: req.Priority,
}
if err := h.store.SetMatrixEntry(c.Request.Context(), entry); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, entry)
}
// DeleteMatrixEntry removes a CTM entry
// DELETE /sdk/v1/training/matrix/:role/:moduleId
func (h *TrainingHandlers) DeleteMatrixEntry(c *gin.Context) {
tenantID := rbac.GetTenantID(c)
role := c.Param("role")
moduleID, err := uuid.Parse(c.Param("moduleId"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid module ID"})
return
}
if err := h.store.DeleteMatrixEntry(c.Request.Context(), tenantID, role, moduleID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "deleted"})
}