Initial commit: breakpilot-compliance - Compliance SDK Platform
Services: Admin-Compliance, Backend-Compliance, AI-Compliance-SDK, Consent-SDK, Developer-Portal, PCA-Platform, DSMS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
327
admin-compliance/ai-compliance-sdk/internal/api/checkpoint.go
Normal file
327
admin-compliance/ai-compliance-sdk/internal/api/checkpoint.go
Normal file
@@ -0,0 +1,327 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Checkpoint represents a checkpoint definition
|
||||
type Checkpoint struct {
|
||||
ID string `json:"id"`
|
||||
Step string `json:"step"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
BlocksProgress bool `json:"blocksProgress"`
|
||||
RequiresReview string `json:"requiresReview"`
|
||||
AutoValidate bool `json:"autoValidate"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// CheckpointHandler handles checkpoint-related requests
|
||||
type CheckpointHandler struct {
|
||||
checkpoints map[string]Checkpoint
|
||||
}
|
||||
|
||||
// NewCheckpointHandler creates a new checkpoint handler
|
||||
func NewCheckpointHandler() *CheckpointHandler {
|
||||
return &CheckpointHandler{
|
||||
checkpoints: initCheckpoints(),
|
||||
}
|
||||
}
|
||||
|
||||
func initCheckpoints() map[string]Checkpoint {
|
||||
return map[string]Checkpoint{
|
||||
"CP-UC": {
|
||||
ID: "CP-UC",
|
||||
Step: "use-case-workshop",
|
||||
Name: "Use Case Erfassung",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Mindestens ein Use Case muss erfasst sein",
|
||||
},
|
||||
"CP-SCAN": {
|
||||
ID: "CP-SCAN",
|
||||
Step: "screening",
|
||||
Name: "System Screening",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "SBOM und Security Scan müssen abgeschlossen sein",
|
||||
},
|
||||
"CP-MOD": {
|
||||
ID: "CP-MOD",
|
||||
Step: "modules",
|
||||
Name: "Modul-Zuweisung",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Mindestens ein Compliance-Modul muss zugewiesen sein",
|
||||
},
|
||||
"CP-REQ": {
|
||||
ID: "CP-REQ",
|
||||
Step: "requirements",
|
||||
Name: "Anforderungen",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Anforderungen müssen aus Regulierungen abgeleitet sein",
|
||||
},
|
||||
"CP-CTRL": {
|
||||
ID: "CP-CTRL",
|
||||
Step: "controls",
|
||||
Name: "Controls",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Controls müssen den Anforderungen zugeordnet sein",
|
||||
},
|
||||
"CP-EVI": {
|
||||
ID: "CP-EVI",
|
||||
Step: "evidence",
|
||||
Name: "Nachweise",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Nachweise für Controls müssen dokumentiert sein",
|
||||
},
|
||||
"CP-CHK": {
|
||||
ID: "CP-CHK",
|
||||
Step: "audit-checklist",
|
||||
Name: "Audit Checklist",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Prüfliste muss generiert und überprüft sein",
|
||||
},
|
||||
"CP-RISK": {
|
||||
ID: "CP-RISK",
|
||||
Step: "risks",
|
||||
Name: "Risikobewertung",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Kritische Risiken müssen Mitigationsmaßnahmen haben",
|
||||
},
|
||||
"CP-AI": {
|
||||
ID: "CP-AI",
|
||||
Step: "ai-act",
|
||||
Name: "AI Act Klassifizierung",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "LEGAL",
|
||||
AutoValidate: false,
|
||||
Description: "KI-System muss klassifiziert sein",
|
||||
},
|
||||
"CP-OBL": {
|
||||
ID: "CP-OBL",
|
||||
Step: "obligations",
|
||||
Name: "Pflichtenübersicht",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Rechtliche Pflichten müssen identifiziert sein",
|
||||
},
|
||||
"CP-DSFA": {
|
||||
ID: "CP-DSFA",
|
||||
Step: "dsfa",
|
||||
Name: "DSFA",
|
||||
Type: "RECOMMENDED",
|
||||
BlocksProgress: false,
|
||||
RequiresReview: "DSB",
|
||||
AutoValidate: false,
|
||||
Description: "Datenschutz-Folgenabschätzung muss erstellt und genehmigt sein",
|
||||
},
|
||||
"CP-TOM": {
|
||||
ID: "CP-TOM",
|
||||
Step: "tom",
|
||||
Name: "TOMs",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "NONE",
|
||||
AutoValidate: true,
|
||||
Description: "Technische und organisatorische Maßnahmen müssen definiert sein",
|
||||
},
|
||||
"CP-VVT": {
|
||||
ID: "CP-VVT",
|
||||
Step: "vvt",
|
||||
Name: "Verarbeitungsverzeichnis",
|
||||
Type: "REQUIRED",
|
||||
BlocksProgress: true,
|
||||
RequiresReview: "DSB",
|
||||
AutoValidate: false,
|
||||
Description: "Verarbeitungsverzeichnis muss vollständig sein",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetAll returns all checkpoint definitions
|
||||
func (h *CheckpointHandler) GetAll(c *gin.Context) {
|
||||
tenantID := c.Query("tenantId")
|
||||
|
||||
checkpointList := make([]Checkpoint, 0, len(h.checkpoints))
|
||||
for _, cp := range h.checkpoints {
|
||||
checkpointList = append(checkpointList, cp)
|
||||
}
|
||||
|
||||
SuccessResponse(c, gin.H{
|
||||
"tenantId": tenantID,
|
||||
"checkpoints": checkpointList,
|
||||
})
|
||||
}
|
||||
|
||||
// Validate validates a specific checkpoint
|
||||
func (h *CheckpointHandler) Validate(c *gin.Context) {
|
||||
var req struct {
|
||||
TenantID string `json:"tenantId" binding:"required"`
|
||||
CheckpointID string `json:"checkpointId" binding:"required"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
|
||||
return
|
||||
}
|
||||
|
||||
checkpoint, ok := h.checkpoints[req.CheckpointID]
|
||||
if !ok {
|
||||
ErrorResponse(c, http.StatusNotFound, "Checkpoint not found", "CHECKPOINT_NOT_FOUND")
|
||||
return
|
||||
}
|
||||
|
||||
// Perform validation based on checkpoint ID
|
||||
result := h.validateCheckpoint(checkpoint, req.Data)
|
||||
|
||||
SuccessResponse(c, result)
|
||||
}
|
||||
|
||||
func (h *CheckpointHandler) validateCheckpoint(checkpoint Checkpoint, data map[string]interface{}) CheckpointResult {
|
||||
result := CheckpointResult{
|
||||
CheckpointID: checkpoint.ID,
|
||||
Passed: true,
|
||||
ValidatedAt: now(),
|
||||
ValidatedBy: "SYSTEM",
|
||||
Errors: []ValidationError{},
|
||||
Warnings: []ValidationError{},
|
||||
}
|
||||
|
||||
// Validation logic based on checkpoint
|
||||
switch checkpoint.ID {
|
||||
case "CP-UC":
|
||||
useCases, _ := data["useCases"].([]interface{})
|
||||
if len(useCases) == 0 {
|
||||
result.Passed = false
|
||||
result.Errors = append(result.Errors, ValidationError{
|
||||
RuleID: "uc-min-count",
|
||||
Field: "useCases",
|
||||
Message: "Mindestens ein Use Case muss erstellt werden",
|
||||
Severity: "ERROR",
|
||||
})
|
||||
}
|
||||
|
||||
case "CP-SCAN":
|
||||
screening, _ := data["screening"].(map[string]interface{})
|
||||
if screening == nil || screening["status"] != "COMPLETED" {
|
||||
result.Passed = false
|
||||
result.Errors = append(result.Errors, ValidationError{
|
||||
RuleID: "scan-complete",
|
||||
Field: "screening",
|
||||
Message: "Security Scan muss abgeschlossen sein",
|
||||
Severity: "ERROR",
|
||||
})
|
||||
}
|
||||
|
||||
case "CP-MOD":
|
||||
modules, _ := data["modules"].([]interface{})
|
||||
if len(modules) == 0 {
|
||||
result.Passed = false
|
||||
result.Errors = append(result.Errors, ValidationError{
|
||||
RuleID: "mod-min-count",
|
||||
Field: "modules",
|
||||
Message: "Mindestens ein Modul muss zugewiesen werden",
|
||||
Severity: "ERROR",
|
||||
})
|
||||
}
|
||||
|
||||
case "CP-RISK":
|
||||
risks, _ := data["risks"].([]interface{})
|
||||
criticalUnmitigated := 0
|
||||
for _, r := range risks {
|
||||
risk, ok := r.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
severity, _ := risk["severity"].(string)
|
||||
if severity == "CRITICAL" || severity == "HIGH" {
|
||||
mitigations, _ := risk["mitigation"].([]interface{})
|
||||
if len(mitigations) == 0 {
|
||||
criticalUnmitigated++
|
||||
}
|
||||
}
|
||||
}
|
||||
if criticalUnmitigated > 0 {
|
||||
result.Passed = false
|
||||
result.Errors = append(result.Errors, ValidationError{
|
||||
RuleID: "critical-risks-mitigated",
|
||||
Field: "risks",
|
||||
Message: "Kritische Risiken ohne Mitigationsmaßnahmen gefunden",
|
||||
Severity: "ERROR",
|
||||
})
|
||||
}
|
||||
|
||||
case "CP-DSFA":
|
||||
dsfa, _ := data["dsfa"].(map[string]interface{})
|
||||
if dsfa == nil {
|
||||
result.Passed = false
|
||||
result.Errors = append(result.Errors, ValidationError{
|
||||
RuleID: "dsfa-exists",
|
||||
Field: "dsfa",
|
||||
Message: "DSFA muss erstellt werden",
|
||||
Severity: "ERROR",
|
||||
})
|
||||
} else if dsfa["status"] != "APPROVED" {
|
||||
result.Warnings = append(result.Warnings, ValidationError{
|
||||
RuleID: "dsfa-approved",
|
||||
Field: "dsfa",
|
||||
Message: "DSFA sollte vom DSB genehmigt werden",
|
||||
Severity: "WARNING",
|
||||
})
|
||||
}
|
||||
|
||||
case "CP-TOM":
|
||||
toms, _ := data["toms"].([]interface{})
|
||||
if len(toms) == 0 {
|
||||
result.Passed = false
|
||||
result.Errors = append(result.Errors, ValidationError{
|
||||
RuleID: "tom-min-count",
|
||||
Field: "toms",
|
||||
Message: "Mindestens eine TOM muss definiert werden",
|
||||
Severity: "ERROR",
|
||||
})
|
||||
}
|
||||
|
||||
case "CP-VVT":
|
||||
vvt, _ := data["vvt"].([]interface{})
|
||||
if len(vvt) == 0 {
|
||||
result.Passed = false
|
||||
result.Errors = append(result.Errors, ValidationError{
|
||||
RuleID: "vvt-min-count",
|
||||
Field: "vvt",
|
||||
Message: "Mindestens eine Verarbeitungstätigkeit muss dokumentiert werden",
|
||||
Severity: "ERROR",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user