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>
161 lines
4.8 KiB
Go
161 lines
4.8 KiB
Go
package ucca
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// TOMControl represents a single TOM control from the control library
|
|
type TOMControl struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
Type string `json:"type"` // ORGANIZATIONAL, TECHNICAL
|
|
ImplementationGuidance string `json:"implementation_guidance,omitempty"`
|
|
Evidence []string `json:"evidence,omitempty"`
|
|
AppliesIf *TOMAppliesIf `json:"applies_if,omitempty"`
|
|
RiskTier string `json:"risk_tier"` // BASELINE, ENHANCED, ADVANCED
|
|
Mappings TOMControlMapping `json:"mappings,omitempty"`
|
|
ReviewFrequency string `json:"review_frequency,omitempty"`
|
|
Priority string `json:"priority"` // CRITICAL, HIGH, MEDIUM, LOW
|
|
Complexity string `json:"complexity,omitempty"`
|
|
DomainID string `json:"domain_id,omitempty"` // set during loading
|
|
}
|
|
|
|
// TOMAppliesIf defines when a control applies
|
|
type TOMAppliesIf struct {
|
|
Field string `json:"field"`
|
|
Operator string `json:"operator"`
|
|
Value interface{} `json:"value"`
|
|
}
|
|
|
|
// TOMControlMapping maps a control to various standards
|
|
type TOMControlMapping struct {
|
|
GDPR []string `json:"gdpr,omitempty"`
|
|
ISO27001 []string `json:"iso27001,omitempty"`
|
|
BSI []string `json:"bsi,omitempty"`
|
|
SDM []string `json:"sdm,omitempty"`
|
|
NIS2 []string `json:"nis2,omitempty"`
|
|
}
|
|
|
|
// TOMControlDomain represents a domain of controls
|
|
type TOMControlDomain struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Objective string `json:"objective"`
|
|
Controls []TOMControl `json:"controls"`
|
|
}
|
|
|
|
// TOMControlLibrary is the top-level structure of the control library
|
|
type TOMControlLibrary struct {
|
|
Schema string `json:"schema"`
|
|
Version string `json:"version"`
|
|
Domains []TOMControlDomain `json:"domains"`
|
|
}
|
|
|
|
// TOMControlIndex provides fast lookup of controls
|
|
type TOMControlIndex struct {
|
|
ByID map[string]*TOMControl
|
|
ByDomain map[string][]*TOMControl
|
|
ByGDPRArticle map[string][]*TOMControl
|
|
AllControls []*TOMControl
|
|
}
|
|
|
|
// LoadTOMControls loads the TOM control library from JSON
|
|
func LoadTOMControls() (*TOMControlIndex, error) {
|
|
data, err := readTOMControlsFile()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var library TOMControlLibrary
|
|
if err := json.Unmarshal(data, &library); err != nil {
|
|
return nil, fmt.Errorf("failed to parse TOM controls: %w", err)
|
|
}
|
|
|
|
return buildTOMIndex(&library), nil
|
|
}
|
|
|
|
func readTOMControlsFile() ([]byte, error) {
|
|
// Try multiple candidate paths
|
|
candidates := []string{
|
|
"policies/tom_controls_v1.json",
|
|
"../policies/tom_controls_v1.json",
|
|
"../../policies/tom_controls_v1.json",
|
|
}
|
|
|
|
// Also try relative to source file
|
|
_, filename, _, ok := runtime.Caller(0)
|
|
if ok {
|
|
srcDir := filepath.Dir(filename)
|
|
candidates = append(candidates,
|
|
filepath.Join(srcDir, "../../policies/tom_controls_v1.json"),
|
|
)
|
|
}
|
|
|
|
for _, p := range candidates {
|
|
abs, err := filepath.Abs(p)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
data, err := os.ReadFile(abs)
|
|
if err == nil {
|
|
return data, nil
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("tom_controls_v1.json not found in any candidate path")
|
|
}
|
|
|
|
func buildTOMIndex(library *TOMControlLibrary) *TOMControlIndex {
|
|
idx := &TOMControlIndex{
|
|
ByID: make(map[string]*TOMControl),
|
|
ByDomain: make(map[string][]*TOMControl),
|
|
ByGDPRArticle: make(map[string][]*TOMControl),
|
|
}
|
|
|
|
for i := range library.Domains {
|
|
domain := &library.Domains[i]
|
|
for j := range domain.Controls {
|
|
ctrl := &domain.Controls[j]
|
|
ctrl.DomainID = domain.ID
|
|
|
|
idx.ByID[ctrl.ID] = ctrl
|
|
idx.ByDomain[domain.ID] = append(idx.ByDomain[domain.ID], ctrl)
|
|
idx.AllControls = append(idx.AllControls, ctrl)
|
|
|
|
// Index by GDPR article
|
|
for _, article := range ctrl.Mappings.GDPR {
|
|
idx.ByGDPRArticle[article] = append(idx.ByGDPRArticle[article], ctrl)
|
|
}
|
|
}
|
|
}
|
|
|
|
return idx
|
|
}
|
|
|
|
// GetControl returns a control by ID
|
|
func (idx *TOMControlIndex) GetControl(id string) (*TOMControl, bool) {
|
|
ctrl, ok := idx.ByID[id]
|
|
return ctrl, ok
|
|
}
|
|
|
|
// GetControlsByDomain returns all controls for a domain
|
|
func (idx *TOMControlIndex) GetControlsByDomain(domain string) []*TOMControl {
|
|
return idx.ByDomain[domain]
|
|
}
|
|
|
|
// GetControlsByGDPRArticle returns controls mapped to a GDPR article
|
|
func (idx *TOMControlIndex) GetControlsByGDPRArticle(article string) []*TOMControl {
|
|
return idx.ByGDPRArticle[article]
|
|
}
|
|
|
|
// ValidateControlID checks if a control ID exists
|
|
func (idx *TOMControlIndex) ValidateControlID(id string) bool {
|
|
_, ok := idx.ByID[id]
|
|
return ok
|
|
}
|