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"` }