// BreakPilot Compliance SDK - Compliance Engine // // UCCA (Unified Compliance Control Assessment) Engine // Evaluates compliance state against 45+ policy rules package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/breakpilot/compliance-sdk/services/compliance-engine/internal/api" "github.com/breakpilot/compliance-sdk/services/compliance-engine/internal/ucca" "github.com/gin-gonic/gin" "go.uber.org/zap" ) func main() { logger, _ := zap.NewProduction() defer logger.Sync() // Load UCCA policies engine, err := ucca.NewEngine("policies") if err != nil { logger.Fatal("Failed to load UCCA policies", zap.Error(err)) } logger.Info("UCCA Engine initialized", zap.Int("rules", engine.RuleCount())) // Set Gin mode if os.Getenv("ENVIRONMENT") == "production" { gin.SetMode(gin.ReleaseMode) } router := gin.New() router.Use(gin.Recovery()) // Health check router.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "healthy", "service": "compliance-engine", "rules": engine.RuleCount(), }) }) // API routes v1 := router.Group("/api/v1") { // Assessment v1.POST("/assess", api.Assess(engine)) v1.POST("/assess/control", api.AssessControl(engine)) v1.POST("/assess/regulation", api.AssessRegulation(engine)) // Score calculation v1.POST("/score", api.CalculateScore(engine)) v1.POST("/score/breakdown", api.ScoreBreakdown(engine)) // Obligations v1.GET("/obligations", api.GetObligations(engine)) v1.GET("/obligations/:regulation", api.GetObligationsByRegulation(engine)) // Controls catalog v1.GET("/controls", api.GetControlsCatalog(engine)) v1.GET("/controls/:domain", api.GetControlsByDomain(engine)) // Policies v1.GET("/policies", api.ListPolicies(engine)) v1.GET("/policies/:id", api.GetPolicy(engine)) } port := os.Getenv("PORT") if port == "" { port = "8081" } srv := &http.Server{ Addr: ":" + port, Handler: router, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, } go func() { logger.Info("Starting Compliance Engine", zap.String("port", port)) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatal("Failed to start server", zap.Error(err)) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit logger.Info("Shutting down...") ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() srv.Shutdown(ctx) }