refactor(go): split portfolio, workshop, training/models, roadmap stores
portfolio/store.go (818 LOC) → store_portfolio.go, store_items.go, store_metrics.go workshop/store.go (793 LOC) → store_sessions.go, store_participants.go, store_responses.go training/models.go (757 LOC) → models_enums.go, models_core.go, models_api.go, models_blocks.go roadmap/store.go (757 LOC) → store_roadmap.go, store_items.go, store_import.go All files under 350 LOC. Zero behavior changes, same package declarations. go vet passes on all five packages. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,757 +0,0 @@
|
||||
package training
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Constants / Enums
|
||||
// ============================================================================
|
||||
|
||||
// RegulationArea represents a compliance regulation area
|
||||
type RegulationArea string
|
||||
|
||||
const (
|
||||
RegulationDSGVO RegulationArea = "dsgvo"
|
||||
RegulationNIS2 RegulationArea = "nis2"
|
||||
RegulationISO27001 RegulationArea = "iso27001"
|
||||
RegulationAIAct RegulationArea = "ai_act"
|
||||
RegulationGeschGehG RegulationArea = "geschgehg"
|
||||
RegulationHinSchG RegulationArea = "hinschg"
|
||||
)
|
||||
|
||||
// FrequencyType represents the training frequency
|
||||
type FrequencyType string
|
||||
|
||||
const (
|
||||
FrequencyOnboarding FrequencyType = "onboarding"
|
||||
FrequencyAnnual FrequencyType = "annual"
|
||||
FrequencyEventTrigger FrequencyType = "event_trigger"
|
||||
FrequencyMicro FrequencyType = "micro"
|
||||
)
|
||||
|
||||
// AssignmentStatus represents the status of a training assignment
|
||||
type AssignmentStatus string
|
||||
|
||||
const (
|
||||
AssignmentStatusPending AssignmentStatus = "pending"
|
||||
AssignmentStatusInProgress AssignmentStatus = "in_progress"
|
||||
AssignmentStatusCompleted AssignmentStatus = "completed"
|
||||
AssignmentStatusOverdue AssignmentStatus = "overdue"
|
||||
AssignmentStatusExpired AssignmentStatus = "expired"
|
||||
)
|
||||
|
||||
// TriggerType represents how a training was assigned
|
||||
type TriggerType string
|
||||
|
||||
const (
|
||||
TriggerOnboarding TriggerType = "onboarding"
|
||||
TriggerAnnual TriggerType = "annual"
|
||||
TriggerEvent TriggerType = "event"
|
||||
TriggerManual TriggerType = "manual"
|
||||
)
|
||||
|
||||
// ContentFormat represents the format of module content
|
||||
type ContentFormat string
|
||||
|
||||
const (
|
||||
ContentFormatMarkdown ContentFormat = "markdown"
|
||||
ContentFormatHTML ContentFormat = "html"
|
||||
)
|
||||
|
||||
// Difficulty represents the difficulty level of a quiz question
|
||||
type Difficulty string
|
||||
|
||||
const (
|
||||
DifficultyEasy Difficulty = "easy"
|
||||
DifficultyMedium Difficulty = "medium"
|
||||
DifficultyHard Difficulty = "hard"
|
||||
)
|
||||
|
||||
// AuditAction represents an action in the audit trail
|
||||
type AuditAction string
|
||||
|
||||
const (
|
||||
AuditActionAssigned AuditAction = "assigned"
|
||||
AuditActionStarted AuditAction = "started"
|
||||
AuditActionCompleted AuditAction = "completed"
|
||||
AuditActionQuizSubmitted AuditAction = "quiz_submitted"
|
||||
AuditActionEscalated AuditAction = "escalated"
|
||||
AuditActionCertificateIssued AuditAction = "certificate_issued"
|
||||
AuditActionContentGenerated AuditAction = "content_generated"
|
||||
)
|
||||
|
||||
// AuditEntityType represents the type of entity in audit log
|
||||
type AuditEntityType string
|
||||
|
||||
const (
|
||||
AuditEntityAssignment AuditEntityType = "assignment"
|
||||
AuditEntityModule AuditEntityType = "module"
|
||||
AuditEntityQuiz AuditEntityType = "quiz"
|
||||
AuditEntityCertificate AuditEntityType = "certificate"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Role Constants
|
||||
// ============================================================================
|
||||
|
||||
const (
|
||||
RoleR1 = "R1" // Geschaeftsfuehrung
|
||||
RoleR2 = "R2" // IT-Leitung
|
||||
RoleR3 = "R3" // DSB
|
||||
RoleR4 = "R4" // ISB
|
||||
RoleR5 = "R5" // HR
|
||||
RoleR6 = "R6" // Einkauf
|
||||
RoleR7 = "R7" // Fachabteilung
|
||||
RoleR8 = "R8" // IT-Admin
|
||||
RoleR9 = "R9" // Alle Mitarbeiter
|
||||
RoleR10 = "R10" // Behoerden / Oeffentlicher Dienst
|
||||
)
|
||||
|
||||
// RoleLabels maps role codes to human-readable labels
|
||||
var RoleLabels = map[string]string{
|
||||
RoleR1: "Geschaeftsfuehrung",
|
||||
RoleR2: "IT-Leitung",
|
||||
RoleR3: "Datenschutzbeauftragter",
|
||||
RoleR4: "Informationssicherheitsbeauftragter",
|
||||
RoleR5: "HR / Personal",
|
||||
RoleR6: "Einkauf / Beschaffung",
|
||||
RoleR7: "Fachabteilung",
|
||||
RoleR8: "IT-Administration",
|
||||
RoleR9: "Alle Mitarbeiter",
|
||||
RoleR10: "Behoerden / Oeffentlicher Dienst",
|
||||
}
|
||||
|
||||
// NIS2RoleMapping maps internal roles to NIS2 levels
|
||||
var NIS2RoleMapping = map[string]string{
|
||||
RoleR1: "N1", // Geschaeftsfuehrung
|
||||
RoleR2: "N2", // IT-Leitung
|
||||
RoleR3: "N3", // DSB
|
||||
RoleR4: "N3", // ISB
|
||||
RoleR5: "N4", // HR
|
||||
RoleR6: "N4", // Einkauf
|
||||
RoleR7: "N5", // Fachabteilung
|
||||
RoleR8: "N2", // IT-Admin
|
||||
RoleR9: "N5", // Alle Mitarbeiter
|
||||
RoleR10: "N4", // Behoerden
|
||||
}
|
||||
|
||||
// TargetAudienceRoleMapping maps canonical control target_audience values to CTM roles
|
||||
var TargetAudienceRoleMapping = map[string][]string{
|
||||
"enterprise": {RoleR1, RoleR4, RoleR5, RoleR6, RoleR7, RoleR9}, // Unternehmen
|
||||
"authority": {RoleR10}, // Behoerden
|
||||
"provider": {RoleR2, RoleR8}, // IT-Dienstleister
|
||||
"all": {RoleR1, RoleR2, RoleR3, RoleR4, RoleR5, RoleR6, RoleR7, RoleR8, RoleR9, RoleR10},
|
||||
}
|
||||
|
||||
// CategoryRoleMapping provides additional role hints based on control category
|
||||
var CategoryRoleMapping = map[string][]string{
|
||||
"encryption": {RoleR2, RoleR8},
|
||||
"authentication": {RoleR2, RoleR8, RoleR9},
|
||||
"network": {RoleR2, RoleR8},
|
||||
"data_protection": {RoleR3, RoleR5, RoleR9},
|
||||
"logging": {RoleR2, RoleR4, RoleR8},
|
||||
"incident": {RoleR1, RoleR4},
|
||||
"continuity": {RoleR1, RoleR2, RoleR4},
|
||||
"compliance": {RoleR1, RoleR3, RoleR4},
|
||||
"supply_chain": {RoleR6},
|
||||
"physical": {RoleR7},
|
||||
"personnel": {RoleR5, RoleR9},
|
||||
"application": {RoleR8},
|
||||
"system": {RoleR2, RoleR8},
|
||||
"risk": {RoleR1, RoleR4},
|
||||
"governance": {RoleR1, RoleR4},
|
||||
"hardware": {RoleR2, RoleR8},
|
||||
"identity": {RoleR2, RoleR3, RoleR8},
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Main Entities
|
||||
// ============================================================================
|
||||
|
||||
// TrainingModule represents a compliance training module
|
||||
type TrainingModule struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
AcademyCourseID *uuid.UUID `json:"academy_course_id,omitempty"`
|
||||
ModuleCode string `json:"module_code"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description,omitempty"`
|
||||
RegulationArea RegulationArea `json:"regulation_area"`
|
||||
NIS2Relevant bool `json:"nis2_relevant"`
|
||||
ISOControls []string `json:"iso_controls"` // JSONB
|
||||
FrequencyType FrequencyType `json:"frequency_type"`
|
||||
ValidityDays int `json:"validity_days"`
|
||||
RiskWeight float64 `json:"risk_weight"`
|
||||
ContentType string `json:"content_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
IsActive bool `json:"is_active"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TrainingMatrixEntry represents a role-to-module mapping in the CTM
|
||||
type TrainingMatrixEntry struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
RoleCode string `json:"role_code"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
IsMandatory bool `json:"is_mandatory"`
|
||||
Priority int `json:"priority"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// Joined fields (optional, populated in queries)
|
||||
ModuleCode string `json:"module_code,omitempty"`
|
||||
ModuleTitle string `json:"module_title,omitempty"`
|
||||
}
|
||||
|
||||
// TrainingAssignment represents a user's training assignment
|
||||
type TrainingAssignment struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
RoleCode string `json:"role_code,omitempty"`
|
||||
TriggerType TriggerType `json:"trigger_type"`
|
||||
TriggerEvent string `json:"trigger_event,omitempty"`
|
||||
Status AssignmentStatus `json:"status"`
|
||||
ProgressPercent int `json:"progress_percent"`
|
||||
QuizScore *float64 `json:"quiz_score,omitempty"`
|
||||
QuizPassed *bool `json:"quiz_passed,omitempty"`
|
||||
QuizAttempts int `json:"quiz_attempts"`
|
||||
StartedAt *time.Time `json:"started_at,omitempty"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
Deadline time.Time `json:"deadline"`
|
||||
CertificateID *uuid.UUID `json:"certificate_id,omitempty"`
|
||||
EscalationLevel int `json:"escalation_level"`
|
||||
LastEscalationAt *time.Time `json:"last_escalation_at,omitempty"`
|
||||
EnrollmentID *uuid.UUID `json:"enrollment_id,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
// Joined fields
|
||||
ModuleCode string `json:"module_code,omitempty"`
|
||||
ModuleTitle string `json:"module_title,omitempty"`
|
||||
}
|
||||
|
||||
// QuizQuestion represents a persistent quiz question for a module
|
||||
type QuizQuestion struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
Question string `json:"question"`
|
||||
Options []string `json:"options"` // JSONB
|
||||
CorrectIndex int `json:"correct_index"`
|
||||
Explanation string `json:"explanation,omitempty"`
|
||||
Difficulty Difficulty `json:"difficulty"`
|
||||
IsActive bool `json:"is_active"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// QuizAttempt represents a single quiz attempt by a user
|
||||
type QuizAttempt struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Answers []QuizAnswer `json:"answers"` // JSONB
|
||||
Score float64 `json:"score"`
|
||||
Passed bool `json:"passed"`
|
||||
CorrectCount int `json:"correct_count"`
|
||||
TotalCount int `json:"total_count"`
|
||||
DurationSeconds *int `json:"duration_seconds,omitempty"`
|
||||
AttemptedAt time.Time `json:"attempted_at"`
|
||||
}
|
||||
|
||||
// QuizAnswer represents a single answer within a quiz attempt
|
||||
type QuizAnswer struct {
|
||||
QuestionID uuid.UUID `json:"question_id"`
|
||||
SelectedIndex int `json:"selected_index"`
|
||||
Correct bool `json:"correct"`
|
||||
}
|
||||
|
||||
// AuditLogEntry represents an entry in the training audit trail
|
||||
type AuditLogEntry struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
UserID *uuid.UUID `json:"user_id,omitempty"`
|
||||
Action AuditAction `json:"action"`
|
||||
EntityType AuditEntityType `json:"entity_type"`
|
||||
EntityID *uuid.UUID `json:"entity_id,omitempty"`
|
||||
Details map[string]interface{} `json:"details"` // JSONB
|
||||
IPAddress string `json:"ip_address,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// ModuleContent represents LLM-generated or manual content for a module
|
||||
type ModuleContent struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
Version int `json:"version"`
|
||||
ContentFormat ContentFormat `json:"content_format"`
|
||||
ContentBody string `json:"content_body"`
|
||||
Summary string `json:"summary,omitempty"`
|
||||
GeneratedBy string `json:"generated_by,omitempty"`
|
||||
LLMModel string `json:"llm_model,omitempty"`
|
||||
IsPublished bool `json:"is_published"`
|
||||
ReviewedBy *uuid.UUID `json:"reviewed_by,omitempty"`
|
||||
ReviewedAt *time.Time `json:"reviewed_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TrainingStats contains aggregated training metrics
|
||||
type TrainingStats struct {
|
||||
TotalModules int `json:"total_modules"`
|
||||
TotalAssignments int `json:"total_assignments"`
|
||||
CompletionRate float64 `json:"completion_rate"`
|
||||
OverdueCount int `json:"overdue_count"`
|
||||
PendingCount int `json:"pending_count"`
|
||||
InProgressCount int `json:"in_progress_count"`
|
||||
CompletedCount int `json:"completed_count"`
|
||||
AvgQuizScore float64 `json:"avg_quiz_score"`
|
||||
AvgCompletionDays float64 `json:"avg_completion_days"`
|
||||
UpcomingDeadlines int `json:"upcoming_deadlines"` // within 7 days
|
||||
}
|
||||
|
||||
// ComplianceGap represents a missing or overdue training requirement
|
||||
type ComplianceGap struct {
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
ModuleCode string `json:"module_code"`
|
||||
ModuleTitle string `json:"module_title"`
|
||||
RegulationArea RegulationArea `json:"regulation_area"`
|
||||
RoleCode string `json:"role_code"`
|
||||
IsMandatory bool `json:"is_mandatory"`
|
||||
AssignmentID *uuid.UUID `json:"assignment_id,omitempty"`
|
||||
Status string `json:"status"` // "missing", "overdue", "expired"
|
||||
Deadline *time.Time `json:"deadline,omitempty"`
|
||||
}
|
||||
|
||||
// EscalationResult represents the result of an escalation check
|
||||
type EscalationResult struct {
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
ModuleTitle string `json:"module_title"`
|
||||
PreviousLevel int `json:"previous_level"`
|
||||
NewLevel int `json:"new_level"`
|
||||
DaysOverdue int `json:"days_overdue"`
|
||||
EscalationLabel string `json:"escalation_label"`
|
||||
}
|
||||
|
||||
// DeadlineInfo represents upcoming deadline information
|
||||
type DeadlineInfo struct {
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
ModuleCode string `json:"module_code"`
|
||||
ModuleTitle string `json:"module_title"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
Deadline time.Time `json:"deadline"`
|
||||
DaysLeft int `json:"days_left"`
|
||||
Status AssignmentStatus `json:"status"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Filter Types
|
||||
// ============================================================================
|
||||
|
||||
// ModuleFilters defines filters for listing modules
|
||||
type ModuleFilters struct {
|
||||
RegulationArea RegulationArea
|
||||
FrequencyType FrequencyType
|
||||
IsActive *bool
|
||||
NIS2Relevant *bool
|
||||
Search string
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// AssignmentFilters defines filters for listing assignments
|
||||
type AssignmentFilters struct {
|
||||
ModuleID *uuid.UUID
|
||||
UserID *uuid.UUID
|
||||
RoleCode string
|
||||
Status AssignmentStatus
|
||||
Overdue *bool
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// AuditLogFilters defines filters for listing audit log entries
|
||||
type AuditLogFilters struct {
|
||||
UserID *uuid.UUID
|
||||
Action AuditAction
|
||||
EntityType AuditEntityType
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// API Request/Response Types
|
||||
// ============================================================================
|
||||
|
||||
// CreateModuleRequest is the API request for creating a training module
|
||||
type CreateModuleRequest struct {
|
||||
ModuleCode string `json:"module_code" binding:"required"`
|
||||
Title string `json:"title" binding:"required"`
|
||||
Description string `json:"description,omitempty"`
|
||||
RegulationArea RegulationArea `json:"regulation_area" binding:"required"`
|
||||
NIS2Relevant bool `json:"nis2_relevant"`
|
||||
ISOControls []string `json:"iso_controls,omitempty"`
|
||||
FrequencyType FrequencyType `json:"frequency_type" binding:"required"`
|
||||
ValidityDays int `json:"validity_days"`
|
||||
RiskWeight float64 `json:"risk_weight"`
|
||||
ContentType string `json:"content_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
}
|
||||
|
||||
// UpdateModuleRequest is the API request for updating a training module
|
||||
type UpdateModuleRequest struct {
|
||||
Title *string `json:"title,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
NIS2Relevant *bool `json:"nis2_relevant,omitempty"`
|
||||
ISOControls []string `json:"iso_controls,omitempty"`
|
||||
ValidityDays *int `json:"validity_days,omitempty"`
|
||||
RiskWeight *float64 `json:"risk_weight,omitempty"`
|
||||
DurationMinutes *int `json:"duration_minutes,omitempty"`
|
||||
PassThreshold *int `json:"pass_threshold,omitempty"`
|
||||
IsActive *bool `json:"is_active,omitempty"`
|
||||
}
|
||||
|
||||
// SetMatrixEntryRequest is the API request for setting a CTM entry
|
||||
type SetMatrixEntryRequest struct {
|
||||
RoleCode string `json:"role_code" binding:"required"`
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
IsMandatory bool `json:"is_mandatory"`
|
||||
Priority int `json:"priority"`
|
||||
}
|
||||
|
||||
// ComputeAssignmentsRequest is the API request for computing assignments
|
||||
type ComputeAssignmentsRequest struct {
|
||||
UserID uuid.UUID `json:"user_id" binding:"required"`
|
||||
UserName string `json:"user_name" binding:"required"`
|
||||
UserEmail string `json:"user_email" binding:"required"`
|
||||
Roles []string `json:"roles" binding:"required"`
|
||||
Trigger string `json:"trigger"`
|
||||
}
|
||||
|
||||
// UpdateAssignmentProgressRequest updates progress on an assignment
|
||||
type UpdateAssignmentProgressRequest struct {
|
||||
Progress int `json:"progress" binding:"required"`
|
||||
}
|
||||
|
||||
// SubmitTrainingQuizRequest is the API request for submitting a quiz
|
||||
type SubmitTrainingQuizRequest struct {
|
||||
AssignmentID uuid.UUID `json:"assignment_id" binding:"required"`
|
||||
Answers []QuizAnswer `json:"answers" binding:"required"`
|
||||
DurationSeconds *int `json:"duration_seconds,omitempty"`
|
||||
}
|
||||
|
||||
// SubmitTrainingQuizResponse is the API response for quiz submission
|
||||
type SubmitTrainingQuizResponse struct {
|
||||
AttemptID uuid.UUID `json:"attempt_id"`
|
||||
Score float64 `json:"score"`
|
||||
Passed bool `json:"passed"`
|
||||
CorrectCount int `json:"correct_count"`
|
||||
TotalCount int `json:"total_count"`
|
||||
Threshold int `json:"threshold"`
|
||||
}
|
||||
|
||||
// GenerateContentRequest is the API request for LLM content generation
|
||||
type GenerateContentRequest struct {
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
||||
// GenerateQuizRequest is the API request for LLM quiz generation
|
||||
type GenerateQuizRequest struct {
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// PublishContentRequest is the API request for publishing content
|
||||
type PublishContentRequest struct {
|
||||
ReviewedBy uuid.UUID `json:"reviewed_by"`
|
||||
}
|
||||
|
||||
// BulkAssignRequest is the API request for bulk assigning a module
|
||||
type BulkAssignRequest struct {
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
RoleCodes []string `json:"role_codes" binding:"required"`
|
||||
Trigger string `json:"trigger"`
|
||||
Deadline time.Time `json:"deadline" binding:"required"`
|
||||
}
|
||||
|
||||
// ModuleListResponse is the API response for listing modules
|
||||
type ModuleListResponse struct {
|
||||
Modules []TrainingModule `json:"modules"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// AssignmentListResponse is the API response for listing assignments
|
||||
type AssignmentListResponse struct {
|
||||
Assignments []TrainingAssignment `json:"assignments"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// MatrixResponse is the API response for the full training matrix
|
||||
type MatrixResponse struct {
|
||||
Entries map[string][]TrainingMatrixEntry `json:"entries"` // role_code -> entries
|
||||
Roles map[string]string `json:"roles"` // role_code -> label
|
||||
}
|
||||
|
||||
// AuditLogResponse is the API response for listing audit log entries
|
||||
type AuditLogResponse struct {
|
||||
Entries []AuditLogEntry `json:"entries"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// EscalationResponse is the API response for escalation check
|
||||
type EscalationResponse struct {
|
||||
Results []EscalationResult `json:"results"`
|
||||
TotalChecked int `json:"total_checked"`
|
||||
Escalated int `json:"escalated"`
|
||||
}
|
||||
|
||||
// DeadlineListResponse is the API response for listing deadlines
|
||||
type DeadlineListResponse struct {
|
||||
Deadlines []DeadlineInfo `json:"deadlines"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// BulkResult holds the result of a bulk generation operation
|
||||
type BulkResult struct {
|
||||
Generated int `json:"generated"`
|
||||
Skipped int `json:"skipped"`
|
||||
Errors []string `json:"errors"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Training Block Types (Controls → Schulungsmodule Pipeline)
|
||||
// ============================================================================
|
||||
|
||||
// TrainingBlockConfig defines how canonical controls are grouped into training modules
|
||||
type TrainingBlockConfig struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
DomainFilter string `json:"domain_filter,omitempty"` // "AUTH", "CRYP", etc.
|
||||
CategoryFilter string `json:"category_filter,omitempty"` // "authentication", etc.
|
||||
SeverityFilter string `json:"severity_filter,omitempty"` // "high", "critical"
|
||||
TargetAudienceFilter string `json:"target_audience_filter,omitempty"` // "enterprise", "authority", "provider", "all"
|
||||
RegulationArea RegulationArea `json:"regulation_area"`
|
||||
ModuleCodePrefix string `json:"module_code_prefix"`
|
||||
FrequencyType FrequencyType `json:"frequency_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
MaxControlsPerModule int `json:"max_controls_per_module"`
|
||||
IsActive bool `json:"is_active"`
|
||||
LastGeneratedAt *time.Time `json:"last_generated_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TrainingBlockControlLink tracks which canonical controls are linked to which module
|
||||
type TrainingBlockControlLink struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
BlockConfigID uuid.UUID `json:"block_config_id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
ControlID string `json:"control_id"`
|
||||
ControlTitle string `json:"control_title"`
|
||||
ControlObjective string `json:"control_objective"`
|
||||
ControlRequirements []string `json:"control_requirements"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// CanonicalControlSummary is a lightweight view on canonical_controls for the training pipeline
|
||||
type CanonicalControlSummary struct {
|
||||
ControlID string `json:"control_id"`
|
||||
Title string `json:"title"`
|
||||
Objective string `json:"objective"`
|
||||
Rationale string `json:"rationale"`
|
||||
Requirements []string `json:"requirements"`
|
||||
Severity string `json:"severity"`
|
||||
Category string `json:"category"`
|
||||
TargetAudience string `json:"target_audience"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// CanonicalControlMeta provides aggregated metadata about canonical controls
|
||||
type CanonicalControlMeta struct {
|
||||
Domains []DomainCount `json:"domains"`
|
||||
Categories []CategoryCount `json:"categories"`
|
||||
Audiences []AudienceCount `json:"audiences"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// DomainCount is a domain with its control count
|
||||
type DomainCount struct {
|
||||
Domain string `json:"domain"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// CategoryCount is a category with its control count
|
||||
type CategoryCount struct {
|
||||
Category string `json:"category"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// AudienceCount is a target audience with its control count
|
||||
type AudienceCount struct {
|
||||
Audience string `json:"audience"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// CreateBlockConfigRequest is the API request for creating a block config
|
||||
type CreateBlockConfigRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description,omitempty"`
|
||||
DomainFilter string `json:"domain_filter,omitempty"`
|
||||
CategoryFilter string `json:"category_filter,omitempty"`
|
||||
SeverityFilter string `json:"severity_filter,omitempty"`
|
||||
TargetAudienceFilter string `json:"target_audience_filter,omitempty"`
|
||||
RegulationArea RegulationArea `json:"regulation_area" binding:"required"`
|
||||
ModuleCodePrefix string `json:"module_code_prefix" binding:"required"`
|
||||
FrequencyType FrequencyType `json:"frequency_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
MaxControlsPerModule int `json:"max_controls_per_module"`
|
||||
}
|
||||
|
||||
// UpdateBlockConfigRequest is the API request for updating a block config
|
||||
type UpdateBlockConfigRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
DomainFilter *string `json:"domain_filter,omitempty"`
|
||||
CategoryFilter *string `json:"category_filter,omitempty"`
|
||||
SeverityFilter *string `json:"severity_filter,omitempty"`
|
||||
TargetAudienceFilter *string `json:"target_audience_filter,omitempty"`
|
||||
MaxControlsPerModule *int `json:"max_controls_per_module,omitempty"`
|
||||
DurationMinutes *int `json:"duration_minutes,omitempty"`
|
||||
PassThreshold *int `json:"pass_threshold,omitempty"`
|
||||
IsActive *bool `json:"is_active,omitempty"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Interactive Video / Checkpoint Types
|
||||
// ============================================================================
|
||||
|
||||
// NarratorScript is an extended VideoScript with narrator persona and checkpoints
|
||||
type NarratorScript struct {
|
||||
Title string `json:"title"`
|
||||
Intro string `json:"intro"`
|
||||
Sections []NarratorSection `json:"sections"`
|
||||
Outro string `json:"outro"`
|
||||
TotalDurationEstimate int `json:"total_duration_estimate"`
|
||||
}
|
||||
|
||||
// NarratorSection is one narrative section with optional checkpoint
|
||||
type NarratorSection struct {
|
||||
Heading string `json:"heading"`
|
||||
NarratorText string `json:"narrator_text"`
|
||||
BulletPoints []string `json:"bullet_points"`
|
||||
Transition string `json:"transition"`
|
||||
Checkpoint *CheckpointDefinition `json:"checkpoint,omitempty"`
|
||||
}
|
||||
|
||||
// CheckpointDefinition defines a quiz checkpoint within a video
|
||||
type CheckpointDefinition struct {
|
||||
Title string `json:"title"`
|
||||
Questions []CheckpointQuestion `json:"questions"`
|
||||
}
|
||||
|
||||
// CheckpointQuestion is a quiz question within a checkpoint
|
||||
type CheckpointQuestion struct {
|
||||
Question string `json:"question"`
|
||||
Options []string `json:"options"`
|
||||
CorrectIndex int `json:"correct_index"`
|
||||
Explanation string `json:"explanation"`
|
||||
}
|
||||
|
||||
// Checkpoint is a DB record for a video checkpoint
|
||||
type Checkpoint struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
CheckpointIndex int `json:"checkpoint_index"`
|
||||
Title string `json:"title"`
|
||||
TimestampSeconds float64 `json:"timestamp_seconds"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// CheckpointProgress tracks a user's progress on a checkpoint
|
||||
type CheckpointProgress struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
CheckpointID uuid.UUID `json:"checkpoint_id"`
|
||||
Passed bool `json:"passed"`
|
||||
Attempts int `json:"attempts"`
|
||||
LastAttemptAt *time.Time `json:"last_attempt_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// InteractiveVideoManifest is returned to the frontend player
|
||||
type InteractiveVideoManifest struct {
|
||||
MediaID uuid.UUID `json:"media_id"`
|
||||
StreamURL string `json:"stream_url"`
|
||||
Checkpoints []CheckpointManifestEntry `json:"checkpoints"`
|
||||
}
|
||||
|
||||
// CheckpointManifestEntry is one checkpoint in the manifest
|
||||
type CheckpointManifestEntry struct {
|
||||
CheckpointID uuid.UUID `json:"checkpoint_id"`
|
||||
Index int `json:"index"`
|
||||
Title string `json:"title"`
|
||||
TimestampSeconds float64 `json:"timestamp_seconds"`
|
||||
Questions []CheckpointQuestion `json:"questions"`
|
||||
Progress *CheckpointProgress `json:"progress,omitempty"`
|
||||
}
|
||||
|
||||
// SubmitCheckpointQuizRequest is the API request for submitting a checkpoint quiz
|
||||
type SubmitCheckpointQuizRequest struct {
|
||||
AssignmentID string `json:"assignment_id"`
|
||||
Answers []int `json:"answers"`
|
||||
}
|
||||
|
||||
// SubmitCheckpointQuizResponse is the API response for a checkpoint quiz submission
|
||||
type SubmitCheckpointQuizResponse struct {
|
||||
Passed bool `json:"passed"`
|
||||
Score float64 `json:"score"`
|
||||
Feedback []CheckpointQuizFeedback `json:"feedback"`
|
||||
}
|
||||
|
||||
// CheckpointQuizFeedback is feedback for a single question
|
||||
type CheckpointQuizFeedback struct {
|
||||
Question string `json:"question"`
|
||||
Correct bool `json:"correct"`
|
||||
Explanation string `json:"explanation"`
|
||||
}
|
||||
|
||||
// GenerateBlockRequest is the API request for generating modules from a block config
|
||||
type GenerateBlockRequest struct {
|
||||
Language string `json:"language"`
|
||||
AutoMatrix bool `json:"auto_matrix"`
|
||||
}
|
||||
|
||||
// PreviewBlockResponse shows what would be generated without writing to DB
|
||||
type PreviewBlockResponse struct {
|
||||
ControlCount int `json:"control_count"`
|
||||
ModuleCount int `json:"module_count"`
|
||||
Controls []CanonicalControlSummary `json:"controls"`
|
||||
ProposedRoles []string `json:"proposed_roles"`
|
||||
}
|
||||
|
||||
// GenerateBlockResponse shows the result of a block generation
|
||||
type GenerateBlockResponse struct {
|
||||
ModulesCreated int `json:"modules_created"`
|
||||
ControlsLinked int `json:"controls_linked"`
|
||||
MatrixEntriesCreated int `json:"matrix_entries_created"`
|
||||
ContentGenerated int `json:"content_generated"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
}
|
||||
141
ai-compliance-sdk/internal/training/models_api.go
Normal file
141
ai-compliance-sdk/internal/training/models_api.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package training
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// API Request/Response Types
|
||||
// ============================================================================
|
||||
|
||||
// CreateModuleRequest is the API request for creating a training module
|
||||
type CreateModuleRequest struct {
|
||||
ModuleCode string `json:"module_code" binding:"required"`
|
||||
Title string `json:"title" binding:"required"`
|
||||
Description string `json:"description,omitempty"`
|
||||
RegulationArea RegulationArea `json:"regulation_area" binding:"required"`
|
||||
NIS2Relevant bool `json:"nis2_relevant"`
|
||||
ISOControls []string `json:"iso_controls,omitempty"`
|
||||
FrequencyType FrequencyType `json:"frequency_type" binding:"required"`
|
||||
ValidityDays int `json:"validity_days"`
|
||||
RiskWeight float64 `json:"risk_weight"`
|
||||
ContentType string `json:"content_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
}
|
||||
|
||||
// UpdateModuleRequest is the API request for updating a training module
|
||||
type UpdateModuleRequest struct {
|
||||
Title *string `json:"title,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
NIS2Relevant *bool `json:"nis2_relevant,omitempty"`
|
||||
ISOControls []string `json:"iso_controls,omitempty"`
|
||||
ValidityDays *int `json:"validity_days,omitempty"`
|
||||
RiskWeight *float64 `json:"risk_weight,omitempty"`
|
||||
DurationMinutes *int `json:"duration_minutes,omitempty"`
|
||||
PassThreshold *int `json:"pass_threshold,omitempty"`
|
||||
IsActive *bool `json:"is_active,omitempty"`
|
||||
}
|
||||
|
||||
// SetMatrixEntryRequest is the API request for setting a CTM entry
|
||||
type SetMatrixEntryRequest struct {
|
||||
RoleCode string `json:"role_code" binding:"required"`
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
IsMandatory bool `json:"is_mandatory"`
|
||||
Priority int `json:"priority"`
|
||||
}
|
||||
|
||||
// ComputeAssignmentsRequest is the API request for computing assignments
|
||||
type ComputeAssignmentsRequest struct {
|
||||
UserID uuid.UUID `json:"user_id" binding:"required"`
|
||||
UserName string `json:"user_name" binding:"required"`
|
||||
UserEmail string `json:"user_email" binding:"required"`
|
||||
Roles []string `json:"roles" binding:"required"`
|
||||
Trigger string `json:"trigger"`
|
||||
}
|
||||
|
||||
// UpdateAssignmentProgressRequest updates progress on an assignment
|
||||
type UpdateAssignmentProgressRequest struct {
|
||||
Progress int `json:"progress" binding:"required"`
|
||||
}
|
||||
|
||||
// SubmitTrainingQuizRequest is the API request for submitting a quiz
|
||||
type SubmitTrainingQuizRequest struct {
|
||||
AssignmentID uuid.UUID `json:"assignment_id" binding:"required"`
|
||||
Answers []QuizAnswer `json:"answers" binding:"required"`
|
||||
DurationSeconds *int `json:"duration_seconds,omitempty"`
|
||||
}
|
||||
|
||||
// SubmitTrainingQuizResponse is the API response for quiz submission
|
||||
type SubmitTrainingQuizResponse struct {
|
||||
AttemptID uuid.UUID `json:"attempt_id"`
|
||||
Score float64 `json:"score"`
|
||||
Passed bool `json:"passed"`
|
||||
CorrectCount int `json:"correct_count"`
|
||||
TotalCount int `json:"total_count"`
|
||||
Threshold int `json:"threshold"`
|
||||
}
|
||||
|
||||
// GenerateContentRequest is the API request for LLM content generation
|
||||
type GenerateContentRequest struct {
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
||||
// GenerateQuizRequest is the API request for LLM quiz generation
|
||||
type GenerateQuizRequest struct {
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// PublishContentRequest is the API request for publishing content
|
||||
type PublishContentRequest struct {
|
||||
ReviewedBy uuid.UUID `json:"reviewed_by"`
|
||||
}
|
||||
|
||||
// BulkAssignRequest is the API request for bulk assigning a module
|
||||
type BulkAssignRequest struct {
|
||||
ModuleID uuid.UUID `json:"module_id" binding:"required"`
|
||||
RoleCodes []string `json:"role_codes" binding:"required"`
|
||||
Trigger string `json:"trigger"`
|
||||
Deadline time.Time `json:"deadline" binding:"required"`
|
||||
}
|
||||
|
||||
// ModuleListResponse is the API response for listing modules
|
||||
type ModuleListResponse struct {
|
||||
Modules []TrainingModule `json:"modules"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// AssignmentListResponse is the API response for listing assignments
|
||||
type AssignmentListResponse struct {
|
||||
Assignments []TrainingAssignment `json:"assignments"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// MatrixResponse is the API response for the full training matrix
|
||||
type MatrixResponse struct {
|
||||
Entries map[string][]TrainingMatrixEntry `json:"entries"` // role_code -> entries
|
||||
Roles map[string]string `json:"roles"` // role_code -> label
|
||||
}
|
||||
|
||||
// AuditLogResponse is the API response for listing audit log entries
|
||||
type AuditLogResponse struct {
|
||||
Entries []AuditLogEntry `json:"entries"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// EscalationResponse is the API response for escalation check
|
||||
type EscalationResponse struct {
|
||||
Results []EscalationResult `json:"results"`
|
||||
TotalChecked int `json:"total_checked"`
|
||||
Escalated int `json:"escalated"`
|
||||
}
|
||||
|
||||
// DeadlineListResponse is the API response for listing deadlines
|
||||
type DeadlineListResponse struct {
|
||||
Deadlines []DeadlineInfo `json:"deadlines"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
193
ai-compliance-sdk/internal/training/models_blocks.go
Normal file
193
ai-compliance-sdk/internal/training/models_blocks.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package training
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Training Block Types (Controls → Schulungsmodule Pipeline)
|
||||
// ============================================================================
|
||||
|
||||
// TrainingBlockConfig defines how canonical controls are grouped into training modules
|
||||
type TrainingBlockConfig struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
DomainFilter string `json:"domain_filter,omitempty"`
|
||||
CategoryFilter string `json:"category_filter,omitempty"`
|
||||
SeverityFilter string `json:"severity_filter,omitempty"`
|
||||
TargetAudienceFilter string `json:"target_audience_filter,omitempty"`
|
||||
RegulationArea RegulationArea `json:"regulation_area"`
|
||||
ModuleCodePrefix string `json:"module_code_prefix"`
|
||||
FrequencyType FrequencyType `json:"frequency_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
MaxControlsPerModule int `json:"max_controls_per_module"`
|
||||
IsActive bool `json:"is_active"`
|
||||
LastGeneratedAt *time.Time `json:"last_generated_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TrainingBlockControlLink tracks which canonical controls are linked to which module
|
||||
type TrainingBlockControlLink struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
BlockConfigID uuid.UUID `json:"block_config_id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
ControlID string `json:"control_id"`
|
||||
ControlTitle string `json:"control_title"`
|
||||
ControlObjective string `json:"control_objective"`
|
||||
ControlRequirements []string `json:"control_requirements"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// CreateBlockConfigRequest is the API request for creating a block config
|
||||
type CreateBlockConfigRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description,omitempty"`
|
||||
DomainFilter string `json:"domain_filter,omitempty"`
|
||||
CategoryFilter string `json:"category_filter,omitempty"`
|
||||
SeverityFilter string `json:"severity_filter,omitempty"`
|
||||
TargetAudienceFilter string `json:"target_audience_filter,omitempty"`
|
||||
RegulationArea RegulationArea `json:"regulation_area" binding:"required"`
|
||||
ModuleCodePrefix string `json:"module_code_prefix" binding:"required"`
|
||||
FrequencyType FrequencyType `json:"frequency_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
MaxControlsPerModule int `json:"max_controls_per_module"`
|
||||
}
|
||||
|
||||
// UpdateBlockConfigRequest is the API request for updating a block config
|
||||
type UpdateBlockConfigRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
DomainFilter *string `json:"domain_filter,omitempty"`
|
||||
CategoryFilter *string `json:"category_filter,omitempty"`
|
||||
SeverityFilter *string `json:"severity_filter,omitempty"`
|
||||
TargetAudienceFilter *string `json:"target_audience_filter,omitempty"`
|
||||
MaxControlsPerModule *int `json:"max_controls_per_module,omitempty"`
|
||||
DurationMinutes *int `json:"duration_minutes,omitempty"`
|
||||
PassThreshold *int `json:"pass_threshold,omitempty"`
|
||||
IsActive *bool `json:"is_active,omitempty"`
|
||||
}
|
||||
|
||||
// GenerateBlockRequest is the API request for generating modules from a block config
|
||||
type GenerateBlockRequest struct {
|
||||
Language string `json:"language"`
|
||||
AutoMatrix bool `json:"auto_matrix"`
|
||||
}
|
||||
|
||||
// PreviewBlockResponse shows what would be generated without writing to DB
|
||||
type PreviewBlockResponse struct {
|
||||
ControlCount int `json:"control_count"`
|
||||
ModuleCount int `json:"module_count"`
|
||||
Controls []CanonicalControlSummary `json:"controls"`
|
||||
ProposedRoles []string `json:"proposed_roles"`
|
||||
}
|
||||
|
||||
// GenerateBlockResponse shows the result of a block generation
|
||||
type GenerateBlockResponse struct {
|
||||
ModulesCreated int `json:"modules_created"`
|
||||
ControlsLinked int `json:"controls_linked"`
|
||||
MatrixEntriesCreated int `json:"matrix_entries_created"`
|
||||
ContentGenerated int `json:"content_generated"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Interactive Video / Checkpoint Types
|
||||
// ============================================================================
|
||||
|
||||
// NarratorScript is an extended VideoScript with narrator persona and checkpoints
|
||||
type NarratorScript struct {
|
||||
Title string `json:"title"`
|
||||
Intro string `json:"intro"`
|
||||
Sections []NarratorSection `json:"sections"`
|
||||
Outro string `json:"outro"`
|
||||
TotalDurationEstimate int `json:"total_duration_estimate"`
|
||||
}
|
||||
|
||||
// NarratorSection is one narrative section with optional checkpoint
|
||||
type NarratorSection struct {
|
||||
Heading string `json:"heading"`
|
||||
NarratorText string `json:"narrator_text"`
|
||||
BulletPoints []string `json:"bullet_points"`
|
||||
Transition string `json:"transition"`
|
||||
Checkpoint *CheckpointDefinition `json:"checkpoint,omitempty"`
|
||||
}
|
||||
|
||||
// CheckpointDefinition defines a quiz checkpoint within a video
|
||||
type CheckpointDefinition struct {
|
||||
Title string `json:"title"`
|
||||
Questions []CheckpointQuestion `json:"questions"`
|
||||
}
|
||||
|
||||
// CheckpointQuestion is a quiz question within a checkpoint
|
||||
type CheckpointQuestion struct {
|
||||
Question string `json:"question"`
|
||||
Options []string `json:"options"`
|
||||
CorrectIndex int `json:"correct_index"`
|
||||
Explanation string `json:"explanation"`
|
||||
}
|
||||
|
||||
// Checkpoint is a DB record for a video checkpoint
|
||||
type Checkpoint struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
CheckpointIndex int `json:"checkpoint_index"`
|
||||
Title string `json:"title"`
|
||||
TimestampSeconds float64 `json:"timestamp_seconds"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// CheckpointProgress tracks a user's progress on a checkpoint
|
||||
type CheckpointProgress struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
CheckpointID uuid.UUID `json:"checkpoint_id"`
|
||||
Passed bool `json:"passed"`
|
||||
Attempts int `json:"attempts"`
|
||||
LastAttemptAt *time.Time `json:"last_attempt_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// InteractiveVideoManifest is returned to the frontend player
|
||||
type InteractiveVideoManifest struct {
|
||||
MediaID uuid.UUID `json:"media_id"`
|
||||
StreamURL string `json:"stream_url"`
|
||||
Checkpoints []CheckpointManifestEntry `json:"checkpoints"`
|
||||
}
|
||||
|
||||
// CheckpointManifestEntry is one checkpoint in the manifest
|
||||
type CheckpointManifestEntry struct {
|
||||
CheckpointID uuid.UUID `json:"checkpoint_id"`
|
||||
Index int `json:"index"`
|
||||
Title string `json:"title"`
|
||||
TimestampSeconds float64 `json:"timestamp_seconds"`
|
||||
Questions []CheckpointQuestion `json:"questions"`
|
||||
Progress *CheckpointProgress `json:"progress,omitempty"`
|
||||
}
|
||||
|
||||
// SubmitCheckpointQuizRequest is the API request for submitting a checkpoint quiz
|
||||
type SubmitCheckpointQuizRequest struct {
|
||||
AssignmentID string `json:"assignment_id"`
|
||||
Answers []int `json:"answers"`
|
||||
}
|
||||
|
||||
// SubmitCheckpointQuizResponse is the API response for a checkpoint quiz submission
|
||||
type SubmitCheckpointQuizResponse struct {
|
||||
Passed bool `json:"passed"`
|
||||
Score float64 `json:"score"`
|
||||
Feedback []CheckpointQuizFeedback `json:"feedback"`
|
||||
}
|
||||
|
||||
// CheckpointQuizFeedback is feedback for a single question
|
||||
type CheckpointQuizFeedback struct {
|
||||
Question string `json:"question"`
|
||||
Correct bool `json:"correct"`
|
||||
Explanation string `json:"explanation"`
|
||||
}
|
||||
276
ai-compliance-sdk/internal/training/models_core.go
Normal file
276
ai-compliance-sdk/internal/training/models_core.go
Normal file
@@ -0,0 +1,276 @@
|
||||
package training
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Main Entities
|
||||
// ============================================================================
|
||||
|
||||
// TrainingModule represents a compliance training module
|
||||
type TrainingModule struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
AcademyCourseID *uuid.UUID `json:"academy_course_id,omitempty"`
|
||||
ModuleCode string `json:"module_code"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description,omitempty"`
|
||||
RegulationArea RegulationArea `json:"regulation_area"`
|
||||
NIS2Relevant bool `json:"nis2_relevant"`
|
||||
ISOControls []string `json:"iso_controls"` // JSONB
|
||||
FrequencyType FrequencyType `json:"frequency_type"`
|
||||
ValidityDays int `json:"validity_days"`
|
||||
RiskWeight float64 `json:"risk_weight"`
|
||||
ContentType string `json:"content_type"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
PassThreshold int `json:"pass_threshold"`
|
||||
IsActive bool `json:"is_active"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TrainingMatrixEntry represents a role-to-module mapping in the CTM
|
||||
type TrainingMatrixEntry struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
RoleCode string `json:"role_code"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
IsMandatory bool `json:"is_mandatory"`
|
||||
Priority int `json:"priority"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// Joined fields (optional, populated in queries)
|
||||
ModuleCode string `json:"module_code,omitempty"`
|
||||
ModuleTitle string `json:"module_title,omitempty"`
|
||||
}
|
||||
|
||||
// TrainingAssignment represents a user's training assignment
|
||||
type TrainingAssignment struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
RoleCode string `json:"role_code,omitempty"`
|
||||
TriggerType TriggerType `json:"trigger_type"`
|
||||
TriggerEvent string `json:"trigger_event,omitempty"`
|
||||
Status AssignmentStatus `json:"status"`
|
||||
ProgressPercent int `json:"progress_percent"`
|
||||
QuizScore *float64 `json:"quiz_score,omitempty"`
|
||||
QuizPassed *bool `json:"quiz_passed,omitempty"`
|
||||
QuizAttempts int `json:"quiz_attempts"`
|
||||
StartedAt *time.Time `json:"started_at,omitempty"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
Deadline time.Time `json:"deadline"`
|
||||
CertificateID *uuid.UUID `json:"certificate_id,omitempty"`
|
||||
EscalationLevel int `json:"escalation_level"`
|
||||
LastEscalationAt *time.Time `json:"last_escalation_at,omitempty"`
|
||||
EnrollmentID *uuid.UUID `json:"enrollment_id,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
// Joined fields
|
||||
ModuleCode string `json:"module_code,omitempty"`
|
||||
ModuleTitle string `json:"module_title,omitempty"`
|
||||
}
|
||||
|
||||
// QuizQuestion represents a persistent quiz question for a module
|
||||
type QuizQuestion struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
Question string `json:"question"`
|
||||
Options []string `json:"options"` // JSONB
|
||||
CorrectIndex int `json:"correct_index"`
|
||||
Explanation string `json:"explanation,omitempty"`
|
||||
Difficulty Difficulty `json:"difficulty"`
|
||||
IsActive bool `json:"is_active"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// QuizAttempt represents a single quiz attempt by a user
|
||||
type QuizAttempt struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Answers []QuizAnswer `json:"answers"` // JSONB
|
||||
Score float64 `json:"score"`
|
||||
Passed bool `json:"passed"`
|
||||
CorrectCount int `json:"correct_count"`
|
||||
TotalCount int `json:"total_count"`
|
||||
DurationSeconds *int `json:"duration_seconds,omitempty"`
|
||||
AttemptedAt time.Time `json:"attempted_at"`
|
||||
}
|
||||
|
||||
// QuizAnswer represents a single answer within a quiz attempt
|
||||
type QuizAnswer struct {
|
||||
QuestionID uuid.UUID `json:"question_id"`
|
||||
SelectedIndex int `json:"selected_index"`
|
||||
Correct bool `json:"correct"`
|
||||
}
|
||||
|
||||
// AuditLogEntry represents an entry in the training audit trail
|
||||
type AuditLogEntry struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TenantID uuid.UUID `json:"tenant_id"`
|
||||
UserID *uuid.UUID `json:"user_id,omitempty"`
|
||||
Action AuditAction `json:"action"`
|
||||
EntityType AuditEntityType `json:"entity_type"`
|
||||
EntityID *uuid.UUID `json:"entity_id,omitempty"`
|
||||
Details map[string]interface{} `json:"details"` // JSONB
|
||||
IPAddress string `json:"ip_address,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// ModuleContent represents LLM-generated or manual content for a module
|
||||
type ModuleContent struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
Version int `json:"version"`
|
||||
ContentFormat ContentFormat `json:"content_format"`
|
||||
ContentBody string `json:"content_body"`
|
||||
Summary string `json:"summary,omitempty"`
|
||||
GeneratedBy string `json:"generated_by,omitempty"`
|
||||
LLMModel string `json:"llm_model,omitempty"`
|
||||
IsPublished bool `json:"is_published"`
|
||||
ReviewedBy *uuid.UUID `json:"reviewed_by,omitempty"`
|
||||
ReviewedAt *time.Time `json:"reviewed_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TrainingStats contains aggregated training metrics
|
||||
type TrainingStats struct {
|
||||
TotalModules int `json:"total_modules"`
|
||||
TotalAssignments int `json:"total_assignments"`
|
||||
CompletionRate float64 `json:"completion_rate"`
|
||||
OverdueCount int `json:"overdue_count"`
|
||||
PendingCount int `json:"pending_count"`
|
||||
InProgressCount int `json:"in_progress_count"`
|
||||
CompletedCount int `json:"completed_count"`
|
||||
AvgQuizScore float64 `json:"avg_quiz_score"`
|
||||
AvgCompletionDays float64 `json:"avg_completion_days"`
|
||||
UpcomingDeadlines int `json:"upcoming_deadlines"` // within 7 days
|
||||
}
|
||||
|
||||
// ComplianceGap represents a missing or overdue training requirement
|
||||
type ComplianceGap struct {
|
||||
ModuleID uuid.UUID `json:"module_id"`
|
||||
ModuleCode string `json:"module_code"`
|
||||
ModuleTitle string `json:"module_title"`
|
||||
RegulationArea RegulationArea `json:"regulation_area"`
|
||||
RoleCode string `json:"role_code"`
|
||||
IsMandatory bool `json:"is_mandatory"`
|
||||
AssignmentID *uuid.UUID `json:"assignment_id,omitempty"`
|
||||
Status string `json:"status"` // "missing", "overdue", "expired"
|
||||
Deadline *time.Time `json:"deadline,omitempty"`
|
||||
}
|
||||
|
||||
// EscalationResult represents the result of an escalation check
|
||||
type EscalationResult struct {
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
UserEmail string `json:"user_email"`
|
||||
ModuleTitle string `json:"module_title"`
|
||||
PreviousLevel int `json:"previous_level"`
|
||||
NewLevel int `json:"new_level"`
|
||||
DaysOverdue int `json:"days_overdue"`
|
||||
EscalationLabel string `json:"escalation_label"`
|
||||
}
|
||||
|
||||
// DeadlineInfo represents upcoming deadline information
|
||||
type DeadlineInfo struct {
|
||||
AssignmentID uuid.UUID `json:"assignment_id"`
|
||||
ModuleCode string `json:"module_code"`
|
||||
ModuleTitle string `json:"module_title"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
Deadline time.Time `json:"deadline"`
|
||||
DaysLeft int `json:"days_left"`
|
||||
Status AssignmentStatus `json:"status"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Filter Types
|
||||
// ============================================================================
|
||||
|
||||
// ModuleFilters defines filters for listing modules
|
||||
type ModuleFilters struct {
|
||||
RegulationArea RegulationArea
|
||||
FrequencyType FrequencyType
|
||||
IsActive *bool
|
||||
NIS2Relevant *bool
|
||||
Search string
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// AssignmentFilters defines filters for listing assignments
|
||||
type AssignmentFilters struct {
|
||||
ModuleID *uuid.UUID
|
||||
UserID *uuid.UUID
|
||||
RoleCode string
|
||||
Status AssignmentStatus
|
||||
Overdue *bool
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// AuditLogFilters defines filters for listing audit log entries
|
||||
type AuditLogFilters struct {
|
||||
UserID *uuid.UUID
|
||||
Action AuditAction
|
||||
EntityType AuditEntityType
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// CanonicalControlSummary is a lightweight view on canonical_controls for the training pipeline
|
||||
type CanonicalControlSummary struct {
|
||||
ControlID string `json:"control_id"`
|
||||
Title string `json:"title"`
|
||||
Objective string `json:"objective"`
|
||||
Rationale string `json:"rationale"`
|
||||
Requirements []string `json:"requirements"`
|
||||
Severity string `json:"severity"`
|
||||
Category string `json:"category"`
|
||||
TargetAudience string `json:"target_audience"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// CanonicalControlMeta provides aggregated metadata about canonical controls
|
||||
type CanonicalControlMeta struct {
|
||||
Domains []DomainCount `json:"domains"`
|
||||
Categories []CategoryCount `json:"categories"`
|
||||
Audiences []AudienceCount `json:"audiences"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// DomainCount is a domain with its control count
|
||||
type DomainCount struct {
|
||||
Domain string `json:"domain"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// CategoryCount is a category with its control count
|
||||
type CategoryCount struct {
|
||||
Category string `json:"category"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// AudienceCount is a target audience with its control count
|
||||
type AudienceCount struct {
|
||||
Audience string `json:"audience"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// BulkResult holds the result of a bulk generation operation
|
||||
type BulkResult struct {
|
||||
Generated int `json:"generated"`
|
||||
Skipped int `json:"skipped"`
|
||||
Errors []string `json:"errors"`
|
||||
}
|
||||
162
ai-compliance-sdk/internal/training/models_enums.go
Normal file
162
ai-compliance-sdk/internal/training/models_enums.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package training
|
||||
|
||||
// ============================================================================
|
||||
// Constants / Enums
|
||||
// ============================================================================
|
||||
|
||||
// RegulationArea represents a compliance regulation area
|
||||
type RegulationArea string
|
||||
|
||||
const (
|
||||
RegulationDSGVO RegulationArea = "dsgvo"
|
||||
RegulationNIS2 RegulationArea = "nis2"
|
||||
RegulationISO27001 RegulationArea = "iso27001"
|
||||
RegulationAIAct RegulationArea = "ai_act"
|
||||
RegulationGeschGehG RegulationArea = "geschgehg"
|
||||
RegulationHinSchG RegulationArea = "hinschg"
|
||||
)
|
||||
|
||||
// FrequencyType represents the training frequency
|
||||
type FrequencyType string
|
||||
|
||||
const (
|
||||
FrequencyOnboarding FrequencyType = "onboarding"
|
||||
FrequencyAnnual FrequencyType = "annual"
|
||||
FrequencyEventTrigger FrequencyType = "event_trigger"
|
||||
FrequencyMicro FrequencyType = "micro"
|
||||
)
|
||||
|
||||
// AssignmentStatus represents the status of a training assignment
|
||||
type AssignmentStatus string
|
||||
|
||||
const (
|
||||
AssignmentStatusPending AssignmentStatus = "pending"
|
||||
AssignmentStatusInProgress AssignmentStatus = "in_progress"
|
||||
AssignmentStatusCompleted AssignmentStatus = "completed"
|
||||
AssignmentStatusOverdue AssignmentStatus = "overdue"
|
||||
AssignmentStatusExpired AssignmentStatus = "expired"
|
||||
)
|
||||
|
||||
// TriggerType represents how a training was assigned
|
||||
type TriggerType string
|
||||
|
||||
const (
|
||||
TriggerOnboarding TriggerType = "onboarding"
|
||||
TriggerAnnual TriggerType = "annual"
|
||||
TriggerEvent TriggerType = "event"
|
||||
TriggerManual TriggerType = "manual"
|
||||
)
|
||||
|
||||
// ContentFormat represents the format of module content
|
||||
type ContentFormat string
|
||||
|
||||
const (
|
||||
ContentFormatMarkdown ContentFormat = "markdown"
|
||||
ContentFormatHTML ContentFormat = "html"
|
||||
)
|
||||
|
||||
// Difficulty represents the difficulty level of a quiz question
|
||||
type Difficulty string
|
||||
|
||||
const (
|
||||
DifficultyEasy Difficulty = "easy"
|
||||
DifficultyMedium Difficulty = "medium"
|
||||
DifficultyHard Difficulty = "hard"
|
||||
)
|
||||
|
||||
// AuditAction represents an action in the audit trail
|
||||
type AuditAction string
|
||||
|
||||
const (
|
||||
AuditActionAssigned AuditAction = "assigned"
|
||||
AuditActionStarted AuditAction = "started"
|
||||
AuditActionCompleted AuditAction = "completed"
|
||||
AuditActionQuizSubmitted AuditAction = "quiz_submitted"
|
||||
AuditActionEscalated AuditAction = "escalated"
|
||||
AuditActionCertificateIssued AuditAction = "certificate_issued"
|
||||
AuditActionContentGenerated AuditAction = "content_generated"
|
||||
)
|
||||
|
||||
// AuditEntityType represents the type of entity in audit log
|
||||
type AuditEntityType string
|
||||
|
||||
const (
|
||||
AuditEntityAssignment AuditEntityType = "assignment"
|
||||
AuditEntityModule AuditEntityType = "module"
|
||||
AuditEntityQuiz AuditEntityType = "quiz"
|
||||
AuditEntityCertificate AuditEntityType = "certificate"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Role Constants
|
||||
// ============================================================================
|
||||
|
||||
const (
|
||||
RoleR1 = "R1" // Geschaeftsfuehrung
|
||||
RoleR2 = "R2" // IT-Leitung
|
||||
RoleR3 = "R3" // DSB
|
||||
RoleR4 = "R4" // ISB
|
||||
RoleR5 = "R5" // HR
|
||||
RoleR6 = "R6" // Einkauf
|
||||
RoleR7 = "R7" // Fachabteilung
|
||||
RoleR8 = "R8" // IT-Admin
|
||||
RoleR9 = "R9" // Alle Mitarbeiter
|
||||
RoleR10 = "R10" // Behoerden / Oeffentlicher Dienst
|
||||
)
|
||||
|
||||
// RoleLabels maps role codes to human-readable labels
|
||||
var RoleLabels = map[string]string{
|
||||
RoleR1: "Geschaeftsfuehrung",
|
||||
RoleR2: "IT-Leitung",
|
||||
RoleR3: "Datenschutzbeauftragter",
|
||||
RoleR4: "Informationssicherheitsbeauftragter",
|
||||
RoleR5: "HR / Personal",
|
||||
RoleR6: "Einkauf / Beschaffung",
|
||||
RoleR7: "Fachabteilung",
|
||||
RoleR8: "IT-Administration",
|
||||
RoleR9: "Alle Mitarbeiter",
|
||||
RoleR10: "Behoerden / Oeffentlicher Dienst",
|
||||
}
|
||||
|
||||
// NIS2RoleMapping maps internal roles to NIS2 levels
|
||||
var NIS2RoleMapping = map[string]string{
|
||||
RoleR1: "N1", // Geschaeftsfuehrung
|
||||
RoleR2: "N2", // IT-Leitung
|
||||
RoleR3: "N3", // DSB
|
||||
RoleR4: "N3", // ISB
|
||||
RoleR5: "N4", // HR
|
||||
RoleR6: "N4", // Einkauf
|
||||
RoleR7: "N5", // Fachabteilung
|
||||
RoleR8: "N2", // IT-Admin
|
||||
RoleR9: "N5", // Alle Mitarbeiter
|
||||
RoleR10: "N4", // Behoerden
|
||||
}
|
||||
|
||||
// TargetAudienceRoleMapping maps canonical control target_audience values to CTM roles
|
||||
var TargetAudienceRoleMapping = map[string][]string{
|
||||
"enterprise": {RoleR1, RoleR4, RoleR5, RoleR6, RoleR7, RoleR9},
|
||||
"authority": {RoleR10},
|
||||
"provider": {RoleR2, RoleR8},
|
||||
"all": {RoleR1, RoleR2, RoleR3, RoleR4, RoleR5, RoleR6, RoleR7, RoleR8, RoleR9, RoleR10},
|
||||
}
|
||||
|
||||
// CategoryRoleMapping provides additional role hints based on control category
|
||||
var CategoryRoleMapping = map[string][]string{
|
||||
"encryption": {RoleR2, RoleR8},
|
||||
"authentication": {RoleR2, RoleR8, RoleR9},
|
||||
"network": {RoleR2, RoleR8},
|
||||
"data_protection": {RoleR3, RoleR5, RoleR9},
|
||||
"logging": {RoleR2, RoleR4, RoleR8},
|
||||
"incident": {RoleR1, RoleR4},
|
||||
"continuity": {RoleR1, RoleR2, RoleR4},
|
||||
"compliance": {RoleR1, RoleR3, RoleR4},
|
||||
"supply_chain": {RoleR6},
|
||||
"physical": {RoleR7},
|
||||
"personnel": {RoleR5, RoleR9},
|
||||
"application": {RoleR8},
|
||||
"system": {RoleR2, RoleR8},
|
||||
"risk": {RoleR1, RoleR4},
|
||||
"governance": {RoleR1, RoleR4},
|
||||
"hardware": {RoleR2, RoleR8},
|
||||
"identity": {RoleR2, RoleR3, RoleR8},
|
||||
}
|
||||
Reference in New Issue
Block a user