feat(ucca): Pflichtendatenbank v2 (325 Obligations), Trigger-Engine, TOM-Control-Mapping
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 32s
CI / test-python-backend-compliance (push) Successful in 29s
CI / test-python-document-crawler (push) Successful in 20s
CI / test-python-dsms-gateway (push) Successful in 18s
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 32s
CI / test-python-backend-compliance (push) Successful in 29s
CI / test-python-document-crawler (push) Successful in 20s
CI / test-python-dsms-gateway (push) Successful in 18s
- 9 Regulation-JSON-Dateien (DSGVO 80, AI Act 60, NIS2 40, BDSG 30, TTDSG 20, DSA 35, Data Act 25, EU-Maschinen 15, DORA 20) - Condition-Tree-Engine fuer automatische Pflichtenselektion (all_of/any_of, 80+ Field-Paths) - Generischer JSONRegulationModule-Loader mit YAML-Fallback - Bidirektionales TOM-Control-Mapping (291 Obligation→Control, 92 Control→Obligation) - Gap-Analyse-Engine (Compliance-%, Priority Actions, Domain Breakdown) - ScopeDecision→UnifiedFacts Bridge fuer Auto-Profiling - 4 neue API-Endpoints (assess-from-scope, tom-controls, gap-analysis, reverse-lookup) - Frontend: Auto-Profiling Button, Regulation-Filter Chips, TOM-Panel, Gap-Analyse-View - 18 Unit Tests (Condition Engine, v2 Loader, TOM Mapper) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -14,23 +15,60 @@ import (
|
||||
|
||||
// ObligationsHandlers handles API requests for the generic obligations framework
|
||||
type ObligationsHandlers struct {
|
||||
registry *ucca.ObligationsRegistry
|
||||
store *ucca.ObligationsStore // Optional: for persisting assessments
|
||||
registry *ucca.ObligationsRegistry
|
||||
store *ucca.ObligationsStore // Optional: for persisting assessments
|
||||
tomIndex *ucca.TOMControlIndex
|
||||
tomMapper *ucca.TOMObligationMapper
|
||||
gapAnalyzer *ucca.TOMGapAnalyzer
|
||||
}
|
||||
|
||||
// NewObligationsHandlers creates a new ObligationsHandlers instance
|
||||
func NewObligationsHandlers() *ObligationsHandlers {
|
||||
return &ObligationsHandlers{
|
||||
h := &ObligationsHandlers{
|
||||
registry: ucca.NewObligationsRegistry(),
|
||||
}
|
||||
h.initTOM()
|
||||
return h
|
||||
}
|
||||
|
||||
// NewObligationsHandlersWithStore creates a new ObligationsHandlers with a store
|
||||
func NewObligationsHandlersWithStore(store *ucca.ObligationsStore) *ObligationsHandlers {
|
||||
return &ObligationsHandlers{
|
||||
h := &ObligationsHandlers{
|
||||
registry: ucca.NewObligationsRegistry(),
|
||||
store: store,
|
||||
}
|
||||
h.initTOM()
|
||||
return h
|
||||
}
|
||||
|
||||
// initTOM initializes TOM control index, mapper, and gap analyzer
|
||||
func (h *ObligationsHandlers) initTOM() {
|
||||
tomIndex, err := ucca.LoadTOMControls()
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: Could not load TOM controls: %v\n", err)
|
||||
return
|
||||
}
|
||||
h.tomIndex = tomIndex
|
||||
|
||||
// Try to load v2 TOM mapping
|
||||
mapping, err := ucca.LoadV2TOMMapping()
|
||||
if err != nil {
|
||||
// Build mapping from v2 regulation files
|
||||
regs, err2 := ucca.LoadAllV2Regulations()
|
||||
if err2 == nil {
|
||||
var allObligations []ucca.V2Obligation
|
||||
for _, reg := range regs {
|
||||
allObligations = append(allObligations, reg.Obligations...)
|
||||
}
|
||||
h.tomMapper = ucca.NewTOMObligationMapperFromObligations(tomIndex, allObligations)
|
||||
}
|
||||
} else {
|
||||
h.tomMapper = ucca.NewTOMObligationMapper(tomIndex, mapping)
|
||||
}
|
||||
|
||||
if h.tomMapper != nil {
|
||||
h.gapAnalyzer = ucca.NewTOMGapAnalyzer(h.tomMapper, tomIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes registers all obligations-related routes
|
||||
@@ -56,6 +94,14 @@ func (h *ObligationsHandlers) RegisterRoutes(r *gin.RouterGroup) {
|
||||
|
||||
// Quick check endpoint (no persistence)
|
||||
obligations.POST("/quick-check", h.QuickCheck)
|
||||
|
||||
// v2: Scope-based assessment
|
||||
obligations.POST("/assess-from-scope", h.AssessFromScope)
|
||||
|
||||
// v2: TOM Control endpoints
|
||||
obligations.GET("/:id/tom-controls", h.GetTOMControlsForObligation)
|
||||
obligations.POST("/gap-analysis", h.GapAnalysis)
|
||||
obligations.GET("/tom-controls/:controlId/obligations", h.GetObligationsForControl)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,6 +469,106 @@ func (h *ObligationsHandlers) QuickCheck(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// AssessFromScope assesses obligations from a ScopeDecision
|
||||
// POST /sdk/v1/ucca/obligations/assess-from-scope
|
||||
func (h *ObligationsHandlers) AssessFromScope(c *gin.Context) {
|
||||
tenantID := rbac.GetTenantID(c)
|
||||
if tenantID == uuid.Nil {
|
||||
tenantID = uuid.New()
|
||||
}
|
||||
|
||||
var scope ucca.ScopeDecision
|
||||
if err := c.ShouldBindJSON(&scope); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Convert scope to facts
|
||||
facts := ucca.MapScopeToFacts(&scope)
|
||||
|
||||
// Evaluate
|
||||
overview := h.registry.EvaluateAll(tenantID, facts, "")
|
||||
|
||||
// Enrich with TOM control requirements if available
|
||||
if h.tomMapper != nil {
|
||||
overview.TOMControlRequirements = h.tomMapper.DeriveControlsFromObligations(overview.Obligations)
|
||||
}
|
||||
|
||||
var warnings []string
|
||||
if len(overview.ApplicableRegulations) == 0 {
|
||||
warnings = append(warnings, "Keine anwendbaren Regulierungen gefunden. Pruefen Sie die Scope-Angaben.")
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, ucca.ObligationsAssessResponse{
|
||||
Overview: overview,
|
||||
Warnings: warnings,
|
||||
})
|
||||
}
|
||||
|
||||
// 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("id")
|
||||
|
||||
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),
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Helper Functions
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user