diff --git a/ai-compliance-sdk/internal/iace/completeness.go b/ai-compliance-sdk/internal/iace/completeness.go index ab1a64e..ed95af8 100644 --- a/ai-compliance-sdk/internal/iace/completeness.go +++ b/ai-compliance-sdk/internal/iace/completeness.go @@ -44,310 +44,6 @@ type CompletenessResult struct { CanExport bool `json:"can_export"` } -// ============================================================================ -// Gate Definitions (25 CE Completeness Gates) -// ============================================================================ - -// buildGateDefinitions returns the full set of 25 CE completeness gate definitions. -func buildGateDefinitions() []GateDefinition { - return []GateDefinition{ - // ===================================================================== - // Onboarding Gates (G01-G08) - Required - // ===================================================================== - { - ID: "G01", - Category: "onboarding", - Label: "Machine identity set", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return ctx.Project != nil && ctx.Project.MachineName != "" - }, - }, - { - ID: "G02", - Category: "onboarding", - Label: "Intended use described", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return ctx.Project != nil && ctx.Project.Description != "" - }, - }, - { - ID: "G03", - Category: "onboarding", - Label: "Operating limits defined", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return ctx.Project != nil && hasMetadataKey(ctx.Project.Metadata, "operating_limits") - }, - }, - { - ID: "G04", - Category: "onboarding", - Label: "Foreseeable misuse documented", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return ctx.Project != nil && hasMetadataKey(ctx.Project.Metadata, "foreseeable_misuse") - }, - }, - { - ID: "G05", - Category: "onboarding", - Label: "Component tree exists", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return len(ctx.Components) > 0 - }, - }, - { - ID: "G06", - Category: "onboarding", - Label: "AI classification done (if applicable)", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - // If no AI present, this gate passes automatically - if !ctx.HasAI { - return true - } - return hasClassificationFor(ctx.Classifications, RegulationAIAct) - }, - }, - { - ID: "G07", - Category: "onboarding", - Label: "Safety relevance marked", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - for _, comp := range ctx.Components { - if comp.IsSafetyRelevant { - return true - } - } - return false - }, - }, - { - ID: "G08", - Category: "onboarding", - Label: "Manufacturer info present", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return ctx.Project != nil && ctx.Project.Manufacturer != "" - }, - }, - - // ===================================================================== - // Pattern Matching Gate (G09) - Recommended - // ===================================================================== - { - ID: "G09", - Category: "onboarding", - Label: "Pattern matching performed", - Required: false, - Recommended: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return ctx.PatternMatchingPerformed - }, - }, - - // ===================================================================== - // Classification Gates (G10-G13) - Required - // ===================================================================== - { - ID: "G10", - Category: "classification", - Label: "AI Act classification complete", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return hasClassificationFor(ctx.Classifications, RegulationAIAct) - }, - }, - { - ID: "G11", - Category: "classification", - Label: "Machinery Regulation check done", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return hasClassificationFor(ctx.Classifications, RegulationMachineryRegulation) - }, - }, - { - ID: "G12", - Category: "classification", - Label: "NIS2 check done", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return hasClassificationFor(ctx.Classifications, RegulationNIS2) - }, - }, - { - ID: "G13", - Category: "classification", - Label: "CRA check done", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return hasClassificationFor(ctx.Classifications, RegulationCRA) - }, - }, - - // ===================================================================== - // Hazard & Risk Gates (G20-G24) - Required - // ===================================================================== - { - ID: "G20", - Category: "hazard_risk", - Label: "Hazards identified", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return len(ctx.Hazards) > 0 - }, - }, - { - ID: "G21", - Category: "hazard_risk", - Label: "All hazards assessed", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - if len(ctx.Hazards) == 0 { - return false - } - // Build a set of hazard IDs that have at least one assessment - assessedHazards := make(map[string]bool) - for _, a := range ctx.Assessments { - assessedHazards[a.HazardID.String()] = true - } - for _, h := range ctx.Hazards { - if !assessedHazards[h.ID.String()] { - return false - } - } - return true - }, - }, - { - ID: "G22", - Category: "hazard_risk", - Label: "Critical/High risks mitigated", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - // Find all hazards that have a critical or high assessment - criticalHighHazards := make(map[string]bool) - for _, a := range ctx.Assessments { - if a.RiskLevel == RiskLevelCritical || a.RiskLevel == RiskLevelHigh { - criticalHighHazards[a.HazardID.String()] = true - } - } - - // If no critical/high hazards, gate passes - if len(criticalHighHazards) == 0 { - return true - } - - // Check that every critical/high hazard has at least one mitigation - mitigatedHazards := make(map[string]bool) - for _, m := range ctx.Mitigations { - mitigatedHazards[m.HazardID.String()] = true - } - - for hazardID := range criticalHighHazards { - if !mitigatedHazards[hazardID] { - return false - } - } - return true - }, - }, - { - ID: "G23", - Category: "hazard_risk", - Label: "Mitigations verified", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - // All mitigations must be in a terminal state (verified or rejected). - // Planned and implemented mitigations block export — they haven't been - // verified yet, so the project cannot be considered complete. - if len(ctx.Mitigations) == 0 { - return true - } - for _, m := range ctx.Mitigations { - if m.Status != MitigationStatusVerified && m.Status != MitigationStatusRejected { - return false - } - } - return true - }, - }, - { - ID: "G24", - Category: "hazard_risk", - Label: "Residual risk accepted", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - if len(ctx.Assessments) == 0 { - return false - } - for _, a := range ctx.Assessments { - if !a.IsAcceptable && a.RiskLevel != RiskLevelLow && a.RiskLevel != RiskLevelNegligible { - return false - } - } - return true - }, - }, - - // ===================================================================== - // Evidence Gate (G30) - Recommended - // ===================================================================== - { - ID: "G30", - Category: "evidence", - Label: "Test evidence linked", - Required: false, - Recommended: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return len(ctx.Evidence) > 0 - }, - }, - - // ===================================================================== - // Tech File Gates (G40-G42) - Required for completion - // ===================================================================== - { - ID: "G40", - Category: "tech_file", - Label: "Risk assessment report generated", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return hasTechFileSection(ctx.TechFileSections, "risk_assessment_report") - }, - }, - { - ID: "G41", - Category: "tech_file", - Label: "Hazard log generated", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - return hasTechFileSection(ctx.TechFileSections, "hazard_log_combined") - }, - }, - { - ID: "G42", - Category: "tech_file", - Label: "AI documents present (if applicable)", - Required: true, - CheckFunc: func(ctx *CompletenessContext) bool { - // If no AI present, this gate passes automatically - if !ctx.HasAI { - return true - } - hasIntendedPurpose := hasTechFileSection(ctx.TechFileSections, "ai_intended_purpose") - hasModelDescription := hasTechFileSection(ctx.TechFileSections, "ai_model_description") - return hasIntendedPurpose && hasModelDescription - }, - }, - } -} - // ============================================================================ // CompletenessChecker // ============================================================================ diff --git a/ai-compliance-sdk/internal/iace/completeness_gates.go b/ai-compliance-sdk/internal/iace/completeness_gates.go new file mode 100644 index 0000000..30821cb --- /dev/null +++ b/ai-compliance-sdk/internal/iace/completeness_gates.go @@ -0,0 +1,305 @@ +package iace + +// ============================================================================ +// Gate Definitions (25 CE Completeness Gates) +// ============================================================================ + +// buildGateDefinitions returns the full set of 25 CE completeness gate definitions. +func buildGateDefinitions() []GateDefinition { + return []GateDefinition{ + // ===================================================================== + // Onboarding Gates (G01-G08) - Required + // ===================================================================== + { + ID: "G01", + Category: "onboarding", + Label: "Machine identity set", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return ctx.Project != nil && ctx.Project.MachineName != "" + }, + }, + { + ID: "G02", + Category: "onboarding", + Label: "Intended use described", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return ctx.Project != nil && ctx.Project.Description != "" + }, + }, + { + ID: "G03", + Category: "onboarding", + Label: "Operating limits defined", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return ctx.Project != nil && hasMetadataKey(ctx.Project.Metadata, "operating_limits") + }, + }, + { + ID: "G04", + Category: "onboarding", + Label: "Foreseeable misuse documented", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return ctx.Project != nil && hasMetadataKey(ctx.Project.Metadata, "foreseeable_misuse") + }, + }, + { + ID: "G05", + Category: "onboarding", + Label: "Component tree exists", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return len(ctx.Components) > 0 + }, + }, + { + ID: "G06", + Category: "onboarding", + Label: "AI classification done (if applicable)", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + // If no AI present, this gate passes automatically + if !ctx.HasAI { + return true + } + return hasClassificationFor(ctx.Classifications, RegulationAIAct) + }, + }, + { + ID: "G07", + Category: "onboarding", + Label: "Safety relevance marked", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + for _, comp := range ctx.Components { + if comp.IsSafetyRelevant { + return true + } + } + return false + }, + }, + { + ID: "G08", + Category: "onboarding", + Label: "Manufacturer info present", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return ctx.Project != nil && ctx.Project.Manufacturer != "" + }, + }, + + // ===================================================================== + // Pattern Matching Gate (G09) - Recommended + // ===================================================================== + { + ID: "G09", + Category: "onboarding", + Label: "Pattern matching performed", + Required: false, + Recommended: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return ctx.PatternMatchingPerformed + }, + }, + + // ===================================================================== + // Classification Gates (G10-G13) - Required + // ===================================================================== + { + ID: "G10", + Category: "classification", + Label: "AI Act classification complete", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return hasClassificationFor(ctx.Classifications, RegulationAIAct) + }, + }, + { + ID: "G11", + Category: "classification", + Label: "Machinery Regulation check done", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return hasClassificationFor(ctx.Classifications, RegulationMachineryRegulation) + }, + }, + { + ID: "G12", + Category: "classification", + Label: "NIS2 check done", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return hasClassificationFor(ctx.Classifications, RegulationNIS2) + }, + }, + { + ID: "G13", + Category: "classification", + Label: "CRA check done", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return hasClassificationFor(ctx.Classifications, RegulationCRA) + }, + }, + + // ===================================================================== + // Hazard & Risk Gates (G20-G24) - Required + // ===================================================================== + { + ID: "G20", + Category: "hazard_risk", + Label: "Hazards identified", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return len(ctx.Hazards) > 0 + }, + }, + { + ID: "G21", + Category: "hazard_risk", + Label: "All hazards assessed", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + if len(ctx.Hazards) == 0 { + return false + } + // Build a set of hazard IDs that have at least one assessment + assessedHazards := make(map[string]bool) + for _, a := range ctx.Assessments { + assessedHazards[a.HazardID.String()] = true + } + for _, h := range ctx.Hazards { + if !assessedHazards[h.ID.String()] { + return false + } + } + return true + }, + }, + { + ID: "G22", + Category: "hazard_risk", + Label: "Critical/High risks mitigated", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + // Find all hazards that have a critical or high assessment + criticalHighHazards := make(map[string]bool) + for _, a := range ctx.Assessments { + if a.RiskLevel == RiskLevelCritical || a.RiskLevel == RiskLevelHigh { + criticalHighHazards[a.HazardID.String()] = true + } + } + + // If no critical/high hazards, gate passes + if len(criticalHighHazards) == 0 { + return true + } + + // Check that every critical/high hazard has at least one mitigation + mitigatedHazards := make(map[string]bool) + for _, m := range ctx.Mitigations { + mitigatedHazards[m.HazardID.String()] = true + } + + for hazardID := range criticalHighHazards { + if !mitigatedHazards[hazardID] { + return false + } + } + return true + }, + }, + { + ID: "G23", + Category: "hazard_risk", + Label: "Mitigations verified", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + // All mitigations must be in a terminal state (verified or rejected). + // Planned and implemented mitigations block export — they haven't been + // verified yet, so the project cannot be considered complete. + if len(ctx.Mitigations) == 0 { + return true + } + for _, m := range ctx.Mitigations { + if m.Status != MitigationStatusVerified && m.Status != MitigationStatusRejected { + return false + } + } + return true + }, + }, + { + ID: "G24", + Category: "hazard_risk", + Label: "Residual risk accepted", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + if len(ctx.Assessments) == 0 { + return false + } + for _, a := range ctx.Assessments { + if !a.IsAcceptable && a.RiskLevel != RiskLevelLow && a.RiskLevel != RiskLevelNegligible { + return false + } + } + return true + }, + }, + + // ===================================================================== + // Evidence Gate (G30) - Recommended + // ===================================================================== + { + ID: "G30", + Category: "evidence", + Label: "Test evidence linked", + Required: false, + Recommended: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return len(ctx.Evidence) > 0 + }, + }, + + // ===================================================================== + // Tech File Gates (G40-G42) - Required for completion + // ===================================================================== + { + ID: "G40", + Category: "tech_file", + Label: "Risk assessment report generated", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return hasTechFileSection(ctx.TechFileSections, "risk_assessment_report") + }, + }, + { + ID: "G41", + Category: "tech_file", + Label: "Hazard log generated", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + return hasTechFileSection(ctx.TechFileSections, "hazard_log_combined") + }, + }, + { + ID: "G42", + Category: "tech_file", + Label: "AI documents present (if applicable)", + Required: true, + CheckFunc: func(ctx *CompletenessContext) bool { + // If no AI present, this gate passes automatically + if !ctx.HasAI { + return true + } + hasIntendedPurpose := hasTechFileSection(ctx.TechFileSections, "ai_intended_purpose") + hasModelDescription := hasTechFileSection(ctx.TechFileSections, "ai_model_description") + return hasIntendedPurpose && hasModelDescription + }, + }, + } +} diff --git a/ai-compliance-sdk/internal/iace/hazard_patterns_extended.go b/ai-compliance-sdk/internal/iace/hazard_patterns_extended.go index 2ac90a3..1d36a0a 100644 --- a/ai-compliance-sdk/internal/iace/hazard_patterns_extended.go +++ b/ai-compliance-sdk/internal/iace/hazard_patterns_extended.go @@ -3,7 +3,13 @@ package iace // GetExtendedHazardPatterns returns 58 additional patterns // derived from the Rule Library documents (R051-R1550). // These supplement the 44 built-in patterns in hazard_patterns.go. +// Patterns HP045-HP073 are defined here; HP074-HP102 in hazard_patterns_extended2.go. func GetExtendedHazardPatterns() []HazardPattern { + return append(getExtendedHazardPatternsA(), getExtendedHazardPatternsB()...) +} + +// getExtendedHazardPatternsA returns patterns HP045-HP073. +func getExtendedHazardPatternsA() []HazardPattern { return []HazardPattern{ { ID: "HP045", NameDE: "Aktor — elektrisch", NameEN: "Actuator — electrical", @@ -324,324 +330,5 @@ func GetExtendedHazardPatterns() []HazardPattern { Priority: 70, // Source: R574, R1074 }, - { - ID: "HP074", NameDE: "Industrie-Switch — elektrisch", NameEN: "Industrial Switch — electrical", - RequiredComponentTags: []string{"networked", "security_device"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"communication_failure"}, - SuggestedMeasureIDs: []string{"M116"}, - SuggestedEvidenceIDs: []string{"E08"}, - Priority: 70, - // Source: R075, R329, R585, R1085 - }, - { - ID: "HP075", NameDE: "Laserscanner — elektrisch", NameEN: "Laser Scanner — electrical", - RequiredComponentTags: []string{"sensor_part"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"sensor_fault"}, - SuggestedMeasureIDs: []string{"M106"}, - SuggestedEvidenceIDs: []string{"E08", "E09"}, - Priority: 70, - // Source: R583, R1083 - }, - { - ID: "HP076", NameDE: "Hubwerk — mechanisch", NameEN: "Lifting Device — mechanical", - RequiredComponentTags: []string{"gravity_risk", "high_force", "moving_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"operation", "transport"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M004", "M005"}, - SuggestedEvidenceIDs: []string{"E08", "E20"}, - Priority: 80, - // Source: R307, R308 - }, - { - ID: "HP077", NameDE: "Hubtisch — hydraulisch", NameEN: "Lifting Table — hydraulic", - RequiredComponentTags: []string{"gravity_risk", "moving_part"}, - RequiredEnergyTags: []string{"hydraulic_pressure"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M021"}, - SuggestedEvidenceIDs: []string{"E11"}, - Priority: 80, - // Source: R560, R1060 - }, - { - ID: "HP078", NameDE: "Linearachse — mechanisch", NameEN: "Linear Axis — mechanical", - RequiredComponentTags: []string{"crush_point", "moving_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"automatic_operation", "maintenance", "setup"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M003", "M051", "M054", "M106", "M121", "M131"}, - SuggestedEvidenceIDs: []string{"E08", "E09", "E20", "E21"}, - Priority: 80, - // Source: R051, R052, R301, R302 - }, - { - ID: "HP079", NameDE: "Maschinenrahmen — mechanisch", NameEN: "Machine Frame — mechanical", - RequiredComponentTags: []string{"structural_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M005"}, - SuggestedEvidenceIDs: []string{"E07"}, - Priority: 80, - // Source: R335, R593, R1093 - }, - { - ID: "HP080", NameDE: "ML-Modell — Software", NameEN: "Ml Model — software", - RequiredComponentTags: []string{"has_ai", "has_software"}, - RequiredEnergyTags: []string{}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"model_drift"}, - SuggestedMeasureIDs: []string{"M103"}, - SuggestedEvidenceIDs: []string{"E15"}, - Priority: 75, - // Source: R078, R332, R589, R1089 - }, - { - ID: "HP081", NameDE: "Ueberwachungssystem — elektrisch", NameEN: "Monitoring System — electrical", - RequiredComponentTags: []string{"has_software", "safety_device"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"sensor_fault"}, - SuggestedMeasureIDs: []string{"M106"}, - SuggestedEvidenceIDs: []string{"E14"}, - Priority: 70, - // Source: R337, R595, R1095 - }, - { - ID: "HP082", NameDE: "Palettierer — mechanisch", NameEN: "Palletizer — mechanical", - RequiredComponentTags: []string{"high_force", "moving_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"automatic_operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M004"}, - SuggestedEvidenceIDs: []string{"E14"}, - Priority: 80, - // Source: R559, R1059 - }, - { - ID: "HP083", NameDE: "Plattform — mechanisch", NameEN: "Platform — mechanical", - RequiredComponentTags: []string{"gravity_risk", "structural_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M052"}, - SuggestedEvidenceIDs: []string{"E20"}, - Priority: 80, - // Source: R336, R594, R1094 - }, - { - ID: "HP084", NameDE: "Pneumatikzylinder — pneumatisch", NameEN: "Pneumatic Cylinder — pneumatic", - RequiredComponentTags: []string{"moving_part", "pneumatic_part", "stored_energy"}, - RequiredEnergyTags: []string{"pneumatic_pressure"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M022"}, - SuggestedEvidenceIDs: []string{"E08"}, - Priority: 80, - // Source: R069, R323, R576, R1076 - }, - { - ID: "HP085", NameDE: "Pneumatikleitung — pneumatisch", NameEN: "Pneumatic Line — pneumatic", - RequiredComponentTags: []string{"pneumatic_part"}, - RequiredEnergyTags: []string{"pneumatic_pressure"}, - RequiredLifecycles: []string{"maintenance"}, - GeneratedHazardCats: []string{"pneumatic_hydraulic"}, - SuggestedMeasureIDs: []string{"M021"}, - SuggestedEvidenceIDs: []string{"E20"}, - Priority: 70, - // Source: R324, R577, R1077 - }, - { - ID: "HP086", NameDE: "Stromversorgung — elektrisch", NameEN: "Power Supply — electrical", - RequiredComponentTags: []string{"electrical_part", "high_voltage"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"maintenance", "operation"}, - GeneratedHazardCats: []string{"electrical_hazard"}, - SuggestedMeasureIDs: []string{"M061", "M121"}, - SuggestedEvidenceIDs: []string{"E14", "E20"}, - Priority: 80, - // Source: R063, R311, R312, R568, R1068 - }, - { - ID: "HP087", NameDE: "Naeherungssensor — elektrisch", NameEN: "Proximity Sensor — electrical", - RequiredComponentTags: []string{"sensor_part"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"sensor_fault"}, - SuggestedMeasureIDs: []string{"M082"}, - SuggestedEvidenceIDs: []string{"E08"}, - Priority: 70, - // Source: R073, R327, R582, R1082 - }, - { - ID: "HP088", NameDE: "Roboterarm — mechanisch", NameEN: "Robot Arm — mechanical", - RequiredComponentTags: []string{"high_force", "moving_part", "rotating_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"automatic_operation", "maintenance", "teach"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M051", "M082", "M106", "M121", "M131"}, - SuggestedEvidenceIDs: []string{"E08", "E09", "E21"}, - Priority: 80, - // Source: R303, R304, R551, R552, R1051, R1052 - }, - { - ID: "HP089", NameDE: "Robotersteuerung — elektrisch", NameEN: "Robot Controller — electrical", - RequiredComponentTags: []string{"has_software", "programmable"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"software_fault"}, - SuggestedMeasureIDs: []string{"M103"}, - SuggestedEvidenceIDs: []string{"E14"}, - Priority: 70, - // Source: R553, R1053 - }, - { - ID: "HP090", NameDE: "Greifer — mechanisch", NameEN: "Robot Gripper — mechanical", - RequiredComponentTags: []string{"clamping_part", "moving_part", "pinch_point"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"automatic_operation", "operation", "setup"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M003", "M004", "M106"}, - SuggestedEvidenceIDs: []string{"E08"}, - Priority: 80, - // Source: R057, R058, R554 - }, - { - ID: "HP091", NameDE: "Greifer — pneumatisch", NameEN: "Robot Gripper — pneumatic", - RequiredComponentTags: []string{"clamping_part", "moving_part", "pinch_point"}, - RequiredEnergyTags: []string{"pneumatic_pressure"}, - RequiredLifecycles: []string{"maintenance", "operation"}, - GeneratedHazardCats: []string{"mechanical_hazard", "pneumatic_hydraulic"}, - SuggestedMeasureIDs: []string{"M004", "M021"}, - SuggestedEvidenceIDs: []string{"E08", "E20"}, - Priority: 80, - // Source: R555, R1054, R1055 - }, - { - ID: "HP092", NameDE: "Rollenfoerderer — mechanisch", NameEN: "Roller Conveyor — mechanical", - RequiredComponentTags: []string{"entanglement_risk", "moving_part", "rotating_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M051"}, - SuggestedEvidenceIDs: []string{"E20"}, - Priority: 80, - // Source: R558, R1058 - }, - { - ID: "HP093", NameDE: "Drehtisch — mechanisch", NameEN: "Rotary Table — mechanical", - RequiredComponentTags: []string{"high_force", "rotating_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"automatic_operation", "maintenance"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M051", "M054", "M121", "M131"}, - SuggestedEvidenceIDs: []string{"E14", "E21"}, - Priority: 80, - // Source: R309, R310 - }, - { - ID: "HP094", NameDE: "Drehscheibe — mechanisch", NameEN: "Rotating Disc — mechanical", - RequiredComponentTags: []string{"high_speed", "rotating_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M051"}, - SuggestedEvidenceIDs: []string{"E20"}, - Priority: 80, - // Source: R565, R1065 - }, - { - ID: "HP095", NameDE: "Spindel — mechanisch", NameEN: "Rotating Spindle — mechanical", - RequiredComponentTags: []string{"cutting_part", "high_speed", "rotating_part"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"maintenance", "operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M051", "M121", "M131"}, - SuggestedEvidenceIDs: []string{"E20", "E21"}, - Priority: 80, - // Source: R561, R562, R1061, R1062 - }, - { - ID: "HP096", NameDE: "Router — elektrisch", NameEN: "Router — electrical", - RequiredComponentTags: []string{"networked", "security_device"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"unauthorized_access"}, - SuggestedMeasureIDs: []string{"M101", "M113"}, - SuggestedEvidenceIDs: []string{"E16", "E17"}, - Priority: 85, - // Source: R076, R330, R586, R1086 - }, - { - ID: "HP097", NameDE: "Gesamtsystem — gemischt", NameEN: "System — mixed", - RequiredComponentTags: []string{"has_software"}, - RequiredEnergyTags: []string{}, - RequiredLifecycles: []string{"operation", "safety_validation"}, - GeneratedHazardCats: []string{"software_fault"}, - SuggestedMeasureIDs: []string{"M082", "M106"}, - SuggestedEvidenceIDs: []string{"E14", "E15"}, - Priority: 70, - // Source: R599, R600, R1099, R1100 - }, - { - ID: "HP098", NameDE: "Werkzeugwechsler — mechanisch", NameEN: "Tool Changer — mechanical", - RequiredComponentTags: []string{"moving_part", "pinch_point"}, - RequiredEnergyTags: []string{"kinetic"}, - RequiredLifecycles: []string{"maintenance", "operation"}, - GeneratedHazardCats: []string{"mechanical_hazard"}, - SuggestedMeasureIDs: []string{"M051"}, - SuggestedEvidenceIDs: []string{"E14", "E20"}, - Priority: 80, - // Source: R059, R060 - }, - { - ID: "HP099", NameDE: "Touch-Bedienfeld — Software", NameEN: "Touch Interface — software", - RequiredComponentTags: []string{"has_software", "user_interface"}, - RequiredEnergyTags: []string{}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"hmi_error"}, - SuggestedMeasureIDs: []string{"M101", "M113"}, - SuggestedEvidenceIDs: []string{"E14"}, - Priority: 70, - // Source: R592, R1092 - }, - { - ID: "HP100", NameDE: "Transformator — elektrisch", NameEN: "Transformer — electrical", - RequiredComponentTags: []string{"electrical_part", "high_voltage"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"inspection", "operation"}, - GeneratedHazardCats: []string{"electrical_hazard", "thermal_hazard"}, - SuggestedMeasureIDs: []string{"M014", "M062"}, - SuggestedEvidenceIDs: []string{"E10"}, - Priority: 80, - // Source: R064, R313, R314, R569, R1069 - }, - { - ID: "HP101", NameDE: "KI-Bilderkennung — Software", NameEN: "Vision Ai — software", - RequiredComponentTags: []string{"has_ai", "sensor_part"}, - RequiredEnergyTags: []string{}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"sensor_fault"}, - SuggestedMeasureIDs: []string{"M103"}, - SuggestedEvidenceIDs: []string{"E15"}, - Priority: 70, - // Source: R077, R331, R588, R1088 - }, - { - ID: "HP102", NameDE: "Vision-Kamera — elektrisch", NameEN: "Vision Camera — electrical", - RequiredComponentTags: []string{"sensor_part"}, - RequiredEnergyTags: []string{"electrical_energy"}, - RequiredLifecycles: []string{"operation"}, - GeneratedHazardCats: []string{"ai_misclassification"}, - SuggestedMeasureIDs: []string{"M082"}, - SuggestedEvidenceIDs: []string{"E20"}, - Priority: 75, - // Source: R584, R1084 - }, } } diff --git a/ai-compliance-sdk/internal/iace/hazard_patterns_extended2.go b/ai-compliance-sdk/internal/iace/hazard_patterns_extended2.go new file mode 100644 index 0000000..ed78847 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/hazard_patterns_extended2.go @@ -0,0 +1,327 @@ +package iace + +// getExtendedHazardPatternsB returns patterns HP074-HP102. +// Called by GetExtendedHazardPatterns in hazard_patterns_extended.go. +func getExtendedHazardPatternsB() []HazardPattern { + return []HazardPattern{ + { + ID: "HP074", NameDE: "Industrie-Switch — elektrisch", NameEN: "Industrial Switch — electrical", + RequiredComponentTags: []string{"networked", "security_device"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"communication_failure"}, + SuggestedMeasureIDs: []string{"M116"}, + SuggestedEvidenceIDs: []string{"E08"}, + Priority: 70, + // Source: R075, R329, R585, R1085 + }, + { + ID: "HP075", NameDE: "Laserscanner — elektrisch", NameEN: "Laser Scanner — electrical", + RequiredComponentTags: []string{"sensor_part"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"sensor_fault"}, + SuggestedMeasureIDs: []string{"M106"}, + SuggestedEvidenceIDs: []string{"E08", "E09"}, + Priority: 70, + // Source: R583, R1083 + }, + { + ID: "HP076", NameDE: "Hubwerk — mechanisch", NameEN: "Lifting Device — mechanical", + RequiredComponentTags: []string{"gravity_risk", "high_force", "moving_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"operation", "transport"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M004", "M005"}, + SuggestedEvidenceIDs: []string{"E08", "E20"}, + Priority: 80, + // Source: R307, R308 + }, + { + ID: "HP077", NameDE: "Hubtisch — hydraulisch", NameEN: "Lifting Table — hydraulic", + RequiredComponentTags: []string{"gravity_risk", "moving_part"}, + RequiredEnergyTags: []string{"hydraulic_pressure"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M021"}, + SuggestedEvidenceIDs: []string{"E11"}, + Priority: 80, + // Source: R560, R1060 + }, + { + ID: "HP078", NameDE: "Linearachse — mechanisch", NameEN: "Linear Axis — mechanical", + RequiredComponentTags: []string{"crush_point", "moving_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"automatic_operation", "maintenance", "setup"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M003", "M051", "M054", "M106", "M121", "M131"}, + SuggestedEvidenceIDs: []string{"E08", "E09", "E20", "E21"}, + Priority: 80, + // Source: R051, R052, R301, R302 + }, + { + ID: "HP079", NameDE: "Maschinenrahmen — mechanisch", NameEN: "Machine Frame — mechanical", + RequiredComponentTags: []string{"structural_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M005"}, + SuggestedEvidenceIDs: []string{"E07"}, + Priority: 80, + // Source: R335, R593, R1093 + }, + { + ID: "HP080", NameDE: "ML-Modell — Software", NameEN: "Ml Model — software", + RequiredComponentTags: []string{"has_ai", "has_software"}, + RequiredEnergyTags: []string{}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"model_drift"}, + SuggestedMeasureIDs: []string{"M103"}, + SuggestedEvidenceIDs: []string{"E15"}, + Priority: 75, + // Source: R078, R332, R589, R1089 + }, + { + ID: "HP081", NameDE: "Ueberwachungssystem — elektrisch", NameEN: "Monitoring System — electrical", + RequiredComponentTags: []string{"has_software", "safety_device"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"sensor_fault"}, + SuggestedMeasureIDs: []string{"M106"}, + SuggestedEvidenceIDs: []string{"E14"}, + Priority: 70, + // Source: R337, R595, R1095 + }, + { + ID: "HP082", NameDE: "Palettierer — mechanisch", NameEN: "Palletizer — mechanical", + RequiredComponentTags: []string{"high_force", "moving_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"automatic_operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M004"}, + SuggestedEvidenceIDs: []string{"E14"}, + Priority: 80, + // Source: R559, R1059 + }, + { + ID: "HP083", NameDE: "Plattform — mechanisch", NameEN: "Platform — mechanical", + RequiredComponentTags: []string{"gravity_risk", "structural_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M052"}, + SuggestedEvidenceIDs: []string{"E20"}, + Priority: 80, + // Source: R336, R594, R1094 + }, + { + ID: "HP084", NameDE: "Pneumatikzylinder — pneumatisch", NameEN: "Pneumatic Cylinder — pneumatic", + RequiredComponentTags: []string{"moving_part", "pneumatic_part", "stored_energy"}, + RequiredEnergyTags: []string{"pneumatic_pressure"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M022"}, + SuggestedEvidenceIDs: []string{"E08"}, + Priority: 80, + // Source: R069, R323, R576, R1076 + }, + { + ID: "HP085", NameDE: "Pneumatikleitung — pneumatisch", NameEN: "Pneumatic Line — pneumatic", + RequiredComponentTags: []string{"pneumatic_part"}, + RequiredEnergyTags: []string{"pneumatic_pressure"}, + RequiredLifecycles: []string{"maintenance"}, + GeneratedHazardCats: []string{"pneumatic_hydraulic"}, + SuggestedMeasureIDs: []string{"M021"}, + SuggestedEvidenceIDs: []string{"E20"}, + Priority: 70, + // Source: R324, R577, R1077 + }, + { + ID: "HP086", NameDE: "Stromversorgung — elektrisch", NameEN: "Power Supply — electrical", + RequiredComponentTags: []string{"electrical_part", "high_voltage"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"maintenance", "operation"}, + GeneratedHazardCats: []string{"electrical_hazard"}, + SuggestedMeasureIDs: []string{"M061", "M121"}, + SuggestedEvidenceIDs: []string{"E14", "E20"}, + Priority: 80, + // Source: R063, R311, R312, R568, R1068 + }, + { + ID: "HP087", NameDE: "Naeherungssensor — elektrisch", NameEN: "Proximity Sensor — electrical", + RequiredComponentTags: []string{"sensor_part"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"sensor_fault"}, + SuggestedMeasureIDs: []string{"M082"}, + SuggestedEvidenceIDs: []string{"E08"}, + Priority: 70, + // Source: R073, R327, R582, R1082 + }, + { + ID: "HP088", NameDE: "Roboterarm — mechanisch", NameEN: "Robot Arm — mechanical", + RequiredComponentTags: []string{"high_force", "moving_part", "rotating_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"automatic_operation", "maintenance", "teach"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M051", "M082", "M106", "M121", "M131"}, + SuggestedEvidenceIDs: []string{"E08", "E09", "E21"}, + Priority: 80, + // Source: R303, R304, R551, R552, R1051, R1052 + }, + { + ID: "HP089", NameDE: "Robotersteuerung — elektrisch", NameEN: "Robot Controller — electrical", + RequiredComponentTags: []string{"has_software", "programmable"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"software_fault"}, + SuggestedMeasureIDs: []string{"M103"}, + SuggestedEvidenceIDs: []string{"E14"}, + Priority: 70, + // Source: R553, R1053 + }, + { + ID: "HP090", NameDE: "Greifer — mechanisch", NameEN: "Robot Gripper — mechanical", + RequiredComponentTags: []string{"clamping_part", "moving_part", "pinch_point"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"automatic_operation", "operation", "setup"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M003", "M004", "M106"}, + SuggestedEvidenceIDs: []string{"E08"}, + Priority: 80, + // Source: R057, R058, R554 + }, + { + ID: "HP091", NameDE: "Greifer — pneumatisch", NameEN: "Robot Gripper — pneumatic", + RequiredComponentTags: []string{"clamping_part", "moving_part", "pinch_point"}, + RequiredEnergyTags: []string{"pneumatic_pressure"}, + RequiredLifecycles: []string{"maintenance", "operation"}, + GeneratedHazardCats: []string{"mechanical_hazard", "pneumatic_hydraulic"}, + SuggestedMeasureIDs: []string{"M004", "M021"}, + SuggestedEvidenceIDs: []string{"E08", "E20"}, + Priority: 80, + // Source: R555, R1054, R1055 + }, + { + ID: "HP092", NameDE: "Rollenfoerderer — mechanisch", NameEN: "Roller Conveyor — mechanical", + RequiredComponentTags: []string{"entanglement_risk", "moving_part", "rotating_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M051"}, + SuggestedEvidenceIDs: []string{"E20"}, + Priority: 80, + // Source: R558, R1058 + }, + { + ID: "HP093", NameDE: "Drehtisch — mechanisch", NameEN: "Rotary Table — mechanical", + RequiredComponentTags: []string{"high_force", "rotating_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"automatic_operation", "maintenance"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M051", "M054", "M121", "M131"}, + SuggestedEvidenceIDs: []string{"E14", "E21"}, + Priority: 80, + // Source: R309, R310 + }, + { + ID: "HP094", NameDE: "Drehscheibe — mechanisch", NameEN: "Rotating Disc — mechanical", + RequiredComponentTags: []string{"high_speed", "rotating_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M051"}, + SuggestedEvidenceIDs: []string{"E20"}, + Priority: 80, + // Source: R565, R1065 + }, + { + ID: "HP095", NameDE: "Spindel — mechanisch", NameEN: "Rotating Spindle — mechanical", + RequiredComponentTags: []string{"cutting_part", "high_speed", "rotating_part"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"maintenance", "operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M051", "M121", "M131"}, + SuggestedEvidenceIDs: []string{"E20", "E21"}, + Priority: 80, + // Source: R561, R562, R1061, R1062 + }, + { + ID: "HP096", NameDE: "Router — elektrisch", NameEN: "Router — electrical", + RequiredComponentTags: []string{"networked", "security_device"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"unauthorized_access"}, + SuggestedMeasureIDs: []string{"M101", "M113"}, + SuggestedEvidenceIDs: []string{"E16", "E17"}, + Priority: 85, + // Source: R076, R330, R586, R1086 + }, + { + ID: "HP097", NameDE: "Gesamtsystem — gemischt", NameEN: "System — mixed", + RequiredComponentTags: []string{"has_software"}, + RequiredEnergyTags: []string{}, + RequiredLifecycles: []string{"operation", "safety_validation"}, + GeneratedHazardCats: []string{"software_fault"}, + SuggestedMeasureIDs: []string{"M082", "M106"}, + SuggestedEvidenceIDs: []string{"E14", "E15"}, + Priority: 70, + // Source: R599, R600, R1099, R1100 + }, + { + ID: "HP098", NameDE: "Werkzeugwechsler — mechanisch", NameEN: "Tool Changer — mechanical", + RequiredComponentTags: []string{"moving_part", "pinch_point"}, + RequiredEnergyTags: []string{"kinetic"}, + RequiredLifecycles: []string{"maintenance", "operation"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M051"}, + SuggestedEvidenceIDs: []string{"E14", "E20"}, + Priority: 80, + // Source: R059, R060 + }, + { + ID: "HP099", NameDE: "Touch-Bedienfeld — Software", NameEN: "Touch Interface — software", + RequiredComponentTags: []string{"has_software", "user_interface"}, + RequiredEnergyTags: []string{}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"hmi_error"}, + SuggestedMeasureIDs: []string{"M101", "M113"}, + SuggestedEvidenceIDs: []string{"E14"}, + Priority: 70, + // Source: R592, R1092 + }, + { + ID: "HP100", NameDE: "Transformator — elektrisch", NameEN: "Transformer — electrical", + RequiredComponentTags: []string{"electrical_part", "high_voltage"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"inspection", "operation"}, + GeneratedHazardCats: []string{"electrical_hazard", "thermal_hazard"}, + SuggestedMeasureIDs: []string{"M014", "M062"}, + SuggestedEvidenceIDs: []string{"E10"}, + Priority: 80, + // Source: R064, R313, R314, R569, R1069 + }, + { + ID: "HP101", NameDE: "KI-Bilderkennung — Software", NameEN: "Vision Ai — software", + RequiredComponentTags: []string{"has_ai", "sensor_part"}, + RequiredEnergyTags: []string{}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"sensor_fault"}, + SuggestedMeasureIDs: []string{"M103"}, + SuggestedEvidenceIDs: []string{"E15"}, + Priority: 70, + // Source: R077, R331, R588, R1088 + }, + { + ID: "HP102", NameDE: "Vision-Kamera — elektrisch", NameEN: "Vision Camera — electrical", + RequiredComponentTags: []string{"sensor_part"}, + RequiredEnergyTags: []string{"electrical_energy"}, + RequiredLifecycles: []string{"operation"}, + GeneratedHazardCats: []string{"ai_misclassification"}, + SuggestedMeasureIDs: []string{"M082"}, + SuggestedEvidenceIDs: []string{"E20"}, + Priority: 75, + // Source: R584, R1084 + }, + } +} diff --git a/ai-compliance-sdk/internal/iace/models.go b/ai-compliance-sdk/internal/iace/models.go index d05e128..f596e12 100644 --- a/ai-compliance-sdk/internal/iace/models.go +++ b/ai-compliance-sdk/internal/iace/models.go @@ -1,12 +1,5 @@ package iace -import ( - "encoding/json" - "time" - - "github.com/google/uuid" -) - // ============================================================================ // Constants / Enums // ============================================================================ @@ -139,11 +132,11 @@ const ( type MonitoringEventType string const ( - MonitoringEventTypeIncident MonitoringEventType = "incident" - MonitoringEventTypeUpdate MonitoringEventType = "update" - MonitoringEventTypeDriftAlert MonitoringEventType = "drift_alert" + MonitoringEventTypeIncident MonitoringEventType = "incident" + MonitoringEventTypeUpdate MonitoringEventType = "update" + MonitoringEventTypeDriftAlert MonitoringEventType = "drift_alert" MonitoringEventTypeRegulationChange MonitoringEventType = "regulation_change" - MonitoringEventTypeAudit MonitoringEventType = "audit" + MonitoringEventTypeAudit MonitoringEventType = "audit" ) // AuditAction represents the type of action recorded in the audit trail @@ -198,427 +191,3 @@ const ( ReviewStatusApproved ReviewStatus = "approved" ReviewStatusRejected ReviewStatus = "rejected" ) - -// ============================================================================ -// Main Entities -// ============================================================================ - -// Project represents an IACE compliance project for a machine or system -type Project struct { - ID uuid.UUID `json:"id"` - TenantID uuid.UUID `json:"tenant_id"` - MachineName string `json:"machine_name"` - MachineType string `json:"machine_type"` - Manufacturer string `json:"manufacturer"` - Description string `json:"description,omitempty"` - NarrativeText string `json:"narrative_text,omitempty"` - Status ProjectStatus `json:"status"` - CEMarkingTarget string `json:"ce_marking_target,omitempty"` - CompletenessScore float64 `json:"completeness_score"` - RiskSummary map[string]int `json:"risk_summary,omitempty"` - TriggeredRegulations json.RawMessage `json:"triggered_regulations,omitempty"` - Metadata json.RawMessage `json:"metadata,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - ArchivedAt *time.Time `json:"archived_at,omitempty"` -} - -// Component represents a system component within a project -type Component struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Name string `json:"name"` - ComponentType ComponentType `json:"component_type"` - Version string `json:"version,omitempty"` - Description string `json:"description,omitempty"` - IsSafetyRelevant bool `json:"is_safety_relevant"` - IsNetworked bool `json:"is_networked"` - Metadata json.RawMessage `json:"metadata,omitempty"` - SortOrder int `json:"sort_order"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// RegulatoryClassification represents the classification result for a regulation -type RegulatoryClassification struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - Regulation RegulationType `json:"regulation"` - ClassificationResult string `json:"classification_result"` - RiskLevel RiskLevel `json:"risk_level"` - Confidence float64 `json:"confidence"` - Reasoning string `json:"reasoning,omitempty"` - RAGSources json.RawMessage `json:"rag_sources,omitempty"` - Requirements json.RawMessage `json:"requirements,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// HazardLibraryEntry represents a reusable hazard template from the library -type HazardLibraryEntry struct { - ID uuid.UUID `json:"id"` - Category string `json:"category"` - SubCategory string `json:"sub_category,omitempty"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - DefaultSeverity int `json:"default_severity"` - DefaultProbability int `json:"default_probability"` - DefaultExposure int `json:"default_exposure,omitempty"` - DefaultAvoidance int `json:"default_avoidance,omitempty"` - ApplicableComponentTypes []string `json:"applicable_component_types"` - RegulationReferences []string `json:"regulation_references"` - SuggestedMitigations json.RawMessage `json:"suggested_mitigations,omitempty"` - TypicalCauses []string `json:"typical_causes,omitempty"` - TypicalHarm string `json:"typical_harm,omitempty"` - RelevantLifecyclePhases []string `json:"relevant_lifecycle_phases,omitempty"` - RecommendedMeasuresDesign []string `json:"recommended_measures_design,omitempty"` - RecommendedMeasuresTechnical []string `json:"recommended_measures_technical,omitempty"` - RecommendedMeasuresInformation []string `json:"recommended_measures_information,omitempty"` - SuggestedEvidence []string `json:"suggested_evidence,omitempty"` - RelatedKeywords []string `json:"related_keywords,omitempty"` - Tags []string `json:"tags,omitempty"` - IsBuiltin bool `json:"is_builtin"` - TenantID *uuid.UUID `json:"tenant_id,omitempty"` - CreatedAt time.Time `json:"created_at"` -} - -// Hazard represents a specific hazard identified within a project -type Hazard struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - ComponentID uuid.UUID `json:"component_id"` - LibraryHazardID *uuid.UUID `json:"library_hazard_id,omitempty"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - Scenario string `json:"scenario,omitempty"` - Category string `json:"category"` - SubCategory string `json:"sub_category,omitempty"` - Status HazardStatus `json:"status"` - MachineModule string `json:"machine_module,omitempty"` - Function string `json:"function,omitempty"` - LifecyclePhase string `json:"lifecycle_phase,omitempty"` - HazardousZone string `json:"hazardous_zone,omitempty"` - TriggerEvent string `json:"trigger_event,omitempty"` - AffectedPerson string `json:"affected_person,omitempty"` - PossibleHarm string `json:"possible_harm,omitempty"` - ReviewStatus ReviewStatus `json:"review_status,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// RiskAssessment represents a quantitative risk assessment for a hazard -type RiskAssessment struct { - ID uuid.UUID `json:"id"` - HazardID uuid.UUID `json:"hazard_id"` - Version int `json:"version"` - AssessmentType AssessmentType `json:"assessment_type"` - Severity int `json:"severity"` - Exposure int `json:"exposure"` - Probability int `json:"probability"` - Avoidance int `json:"avoidance,omitempty"` // 0=disabled, 1-5 (3=neutral) - InherentRisk float64 `json:"inherent_risk"` - ControlMaturity int `json:"control_maturity"` - ControlCoverage float64 `json:"control_coverage"` - TestEvidenceStrength float64 `json:"test_evidence_strength"` - CEff float64 `json:"c_eff"` - ResidualRisk float64 `json:"residual_risk"` - RiskLevel RiskLevel `json:"risk_level"` - IsAcceptable bool `json:"is_acceptable"` - AcceptanceJustification string `json:"acceptance_justification,omitempty"` - AssessedBy uuid.UUID `json:"assessed_by"` - CreatedAt time.Time `json:"created_at"` -} - -// Mitigation represents a risk reduction measure applied to a hazard -type Mitigation struct { - ID uuid.UUID `json:"id"` - HazardID uuid.UUID `json:"hazard_id"` - ReductionType ReductionType `json:"reduction_type"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - Status MitigationStatus `json:"status"` - VerificationMethod VerificationMethod `json:"verification_method,omitempty"` - VerificationResult string `json:"verification_result,omitempty"` - VerifiedAt *time.Time `json:"verified_at,omitempty"` - VerifiedBy uuid.UUID `json:"verified_by,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// Evidence represents an uploaded file that serves as evidence for compliance -type Evidence struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - MitigationID *uuid.UUID `json:"mitigation_id,omitempty"` - VerificationPlanID *uuid.UUID `json:"verification_plan_id,omitempty"` - FileName string `json:"file_name"` - FilePath string `json:"file_path"` - FileHash string `json:"file_hash"` - FileSize int64 `json:"file_size"` - MimeType string `json:"mime_type"` - Description string `json:"description,omitempty"` - UploadedBy uuid.UUID `json:"uploaded_by"` - CreatedAt time.Time `json:"created_at"` -} - -// VerificationPlan represents a plan for verifying compliance measures -type VerificationPlan struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - HazardID *uuid.UUID `json:"hazard_id,omitempty"` - MitigationID *uuid.UUID `json:"mitigation_id,omitempty"` - Title string `json:"title"` - Description string `json:"description,omitempty"` - AcceptanceCriteria string `json:"acceptance_criteria,omitempty"` - Method VerificationMethod `json:"method"` - Status string `json:"status"` - Result string `json:"result,omitempty"` - CompletedAt *time.Time `json:"completed_at,omitempty"` - CompletedBy uuid.UUID `json:"completed_by,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// TechFileSection represents a section of the technical documentation file -type TechFileSection struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - SectionType string `json:"section_type"` - Title string `json:"title"` - Content string `json:"content,omitempty"` - Version int `json:"version"` - Status TechFileSectionStatus `json:"status"` - ApprovedBy uuid.UUID `json:"approved_by,omitempty"` - ApprovedAt *time.Time `json:"approved_at,omitempty"` - Metadata json.RawMessage `json:"metadata,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// MonitoringEvent represents a post-market monitoring event -type MonitoringEvent struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - EventType MonitoringEventType `json:"event_type"` - Title string `json:"title"` - Description string `json:"description,omitempty"` - Severity string `json:"severity"` - ImpactAssessment string `json:"impact_assessment,omitempty"` - Status string `json:"status"` - ResolvedAt *time.Time `json:"resolved_at,omitempty"` - ResolvedBy uuid.UUID `json:"resolved_by,omitempty"` - Metadata json.RawMessage `json:"metadata,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// AuditTrailEntry represents an immutable audit log entry for compliance traceability -type AuditTrailEntry struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"project_id"` - EntityType string `json:"entity_type"` - EntityID uuid.UUID `json:"entity_id"` - Action AuditAction `json:"action"` - UserID uuid.UUID `json:"user_id"` - OldValues json.RawMessage `json:"old_values,omitempty"` - NewValues json.RawMessage `json:"new_values,omitempty"` - Hash string `json:"hash"` - CreatedAt time.Time `json:"created_at"` -} - -// ============================================================================ -// API Request Types -// ============================================================================ - -// CreateProjectRequest is the API request for creating a new IACE project -type CreateProjectRequest struct { - MachineName string `json:"machine_name" binding:"required"` - MachineType string `json:"machine_type" binding:"required"` - Manufacturer string `json:"manufacturer" binding:"required"` - Description string `json:"description,omitempty"` - NarrativeText string `json:"narrative_text,omitempty"` - CEMarkingTarget string `json:"ce_marking_target,omitempty"` - Metadata json.RawMessage `json:"metadata,omitempty"` -} - -// UpdateProjectRequest is the API request for updating an existing project -type UpdateProjectRequest struct { - MachineName *string `json:"machine_name,omitempty"` - MachineType *string `json:"machine_type,omitempty"` - Manufacturer *string `json:"manufacturer,omitempty"` - Description *string `json:"description,omitempty"` - NarrativeText *string `json:"narrative_text,omitempty"` - CEMarkingTarget *string `json:"ce_marking_target,omitempty"` - Metadata *json.RawMessage `json:"metadata,omitempty"` -} - -// CreateComponentRequest is the API request for adding a component to a project -type CreateComponentRequest struct { - ProjectID uuid.UUID `json:"project_id" binding:"required"` - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Name string `json:"name" binding:"required"` - ComponentType ComponentType `json:"component_type" binding:"required"` - Version string `json:"version,omitempty"` - Description string `json:"description,omitempty"` - IsSafetyRelevant bool `json:"is_safety_relevant"` - IsNetworked bool `json:"is_networked"` -} - -// CreateHazardRequest is the API request for creating a new hazard -type CreateHazardRequest struct { - ProjectID uuid.UUID `json:"project_id" binding:"required"` - ComponentID uuid.UUID `json:"component_id" binding:"required"` - LibraryHazardID *uuid.UUID `json:"library_hazard_id,omitempty"` - Name string `json:"name" binding:"required"` - Description string `json:"description,omitempty"` - Scenario string `json:"scenario,omitempty"` - Category string `json:"category" binding:"required"` - SubCategory string `json:"sub_category,omitempty"` - MachineModule string `json:"machine_module,omitempty"` - Function string `json:"function,omitempty"` - LifecyclePhase string `json:"lifecycle_phase,omitempty"` - HazardousZone string `json:"hazardous_zone,omitempty"` - TriggerEvent string `json:"trigger_event,omitempty"` - AffectedPerson string `json:"affected_person,omitempty"` - PossibleHarm string `json:"possible_harm,omitempty"` -} - -// AssessRiskRequest is the API request for performing a risk assessment -type AssessRiskRequest struct { - HazardID uuid.UUID `json:"hazard_id" binding:"required"` - Severity int `json:"severity" binding:"required"` - Exposure int `json:"exposure" binding:"required"` - Probability int `json:"probability" binding:"required"` - Avoidance int `json:"avoidance,omitempty"` // 0=disabled, 1-5 (3=neutral) - ControlMaturity int `json:"control_maturity" binding:"required"` - ControlCoverage float64 `json:"control_coverage" binding:"required"` - TestEvidenceStrength float64 `json:"test_evidence_strength" binding:"required"` - AcceptanceJustification string `json:"acceptance_justification,omitempty"` -} - -// CreateMitigationRequest is the API request for creating a mitigation measure -type CreateMitigationRequest struct { - HazardID uuid.UUID `json:"hazard_id" binding:"required"` - ReductionType ReductionType `json:"reduction_type" binding:"required"` - Name string `json:"name" binding:"required"` - Description string `json:"description,omitempty"` -} - -// CreateVerificationPlanRequest is the API request for creating a verification plan -type CreateVerificationPlanRequest struct { - ProjectID uuid.UUID `json:"project_id" binding:"required"` - HazardID *uuid.UUID `json:"hazard_id,omitempty"` - MitigationID *uuid.UUID `json:"mitigation_id,omitempty"` - Title string `json:"title" binding:"required"` - Description string `json:"description,omitempty"` - AcceptanceCriteria string `json:"acceptance_criteria,omitempty"` - Method VerificationMethod `json:"method" binding:"required"` -} - -// CreateMonitoringEventRequest is the API request for logging a monitoring event -type CreateMonitoringEventRequest struct { - ProjectID uuid.UUID `json:"project_id" binding:"required"` - EventType MonitoringEventType `json:"event_type" binding:"required"` - Title string `json:"title" binding:"required"` - Description string `json:"description,omitempty"` - Severity string `json:"severity" binding:"required"` -} - -// InitFromProfileRequest is the API request for initializing a project from a company profile -type InitFromProfileRequest struct { - CompanyProfile json.RawMessage `json:"company_profile" binding:"required"` - ComplianceScope json.RawMessage `json:"compliance_scope" binding:"required"` -} - -// ============================================================================ -// API Response Types -// ============================================================================ - -// ProjectListResponse is the API response for listing projects -type ProjectListResponse struct { - Projects []Project `json:"projects"` - Total int `json:"total"` -} - -// ProjectDetailResponse is the API response for a single project with related entities -type ProjectDetailResponse struct { - Project - Components []Component `json:"components"` - Classifications []RegulatoryClassification `json:"classifications"` - CompletenessGates []CompletenessGate `json:"completeness_gates"` -} - -// RiskSummaryResponse is the API response for an aggregated risk overview -type RiskSummaryResponse struct { - TotalHazards int `json:"total_hazards"` - NotAcceptable int `json:"not_acceptable,omitempty"` - VeryHigh int `json:"very_high,omitempty"` - Critical int `json:"critical"` - High int `json:"high"` - Medium int `json:"medium"` - Low int `json:"low"` - Negligible int `json:"negligible"` - OverallRiskLevel RiskLevel `json:"overall_risk_level"` - AllAcceptable bool `json:"all_acceptable"` -} - -// LifecyclePhaseInfo represents a machine lifecycle phase with labels -type LifecyclePhaseInfo struct { - ID string `json:"id"` - LabelDE string `json:"label_de"` - LabelEN string `json:"label_en"` - Sort int `json:"sort_order"` -} - -// RoleInfo represents an affected person role with labels -type RoleInfo struct { - ID string `json:"id"` - LabelDE string `json:"label_de"` - LabelEN string `json:"label_en"` - Sort int `json:"sort_order"` -} - -// EvidenceTypeInfo represents an evidence/verification type with labels -type EvidenceTypeInfo struct { - ID string `json:"id"` - Category string `json:"category"` - LabelDE string `json:"label_de"` - LabelEN string `json:"label_en"` - Tags []string `json:"tags,omitempty"` - Sort int `json:"sort_order"` -} - -// ProtectiveMeasureEntry represents a protective measure from the library -type ProtectiveMeasureEntry struct { - ID string `json:"id"` - ReductionType string `json:"reduction_type"` - SubType string `json:"sub_type,omitempty"` - Name string `json:"name"` - Description string `json:"description"` - HazardCategory string `json:"hazard_category,omitempty"` - Examples []string `json:"examples,omitempty"` - Tags []string `json:"tags,omitempty"` -} - -// ValidateMitigationHierarchyRequest is the request for hierarchy validation -type ValidateMitigationHierarchyRequest struct { - HazardID uuid.UUID `json:"hazard_id" binding:"required"` - ReductionType ReductionType `json:"reduction_type" binding:"required"` -} - -// ValidateMitigationHierarchyResponse is the response from hierarchy validation -type ValidateMitigationHierarchyResponse struct { - Valid bool `json:"valid"` - Warnings []string `json:"warnings,omitempty"` -} - -// CompletenessGate represents a single gate in the project completeness checklist -type CompletenessGate struct { - ID string `json:"id"` - Category string `json:"category"` - Label string `json:"label"` - Required bool `json:"required"` - Passed bool `json:"passed"` - Details string `json:"details,omitempty"` -} diff --git a/ai-compliance-sdk/internal/iace/models_api.go b/ai-compliance-sdk/internal/iace/models_api.go new file mode 100644 index 0000000..eb873a7 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/models_api.go @@ -0,0 +1,203 @@ +package iace + +import ( + "encoding/json" + + "github.com/google/uuid" +) + +// ============================================================================ +// API Request Types +// ============================================================================ + +// CreateProjectRequest is the API request for creating a new IACE project +type CreateProjectRequest struct { + MachineName string `json:"machine_name" binding:"required"` + MachineType string `json:"machine_type" binding:"required"` + Manufacturer string `json:"manufacturer" binding:"required"` + Description string `json:"description,omitempty"` + NarrativeText string `json:"narrative_text,omitempty"` + CEMarkingTarget string `json:"ce_marking_target,omitempty"` + Metadata json.RawMessage `json:"metadata,omitempty"` +} + +// UpdateProjectRequest is the API request for updating an existing project +type UpdateProjectRequest struct { + MachineName *string `json:"machine_name,omitempty"` + MachineType *string `json:"machine_type,omitempty"` + Manufacturer *string `json:"manufacturer,omitempty"` + Description *string `json:"description,omitempty"` + NarrativeText *string `json:"narrative_text,omitempty"` + CEMarkingTarget *string `json:"ce_marking_target,omitempty"` + Metadata *json.RawMessage `json:"metadata,omitempty"` +} + +// CreateComponentRequest is the API request for adding a component to a project +type CreateComponentRequest struct { + ProjectID uuid.UUID `json:"project_id" binding:"required"` + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Name string `json:"name" binding:"required"` + ComponentType ComponentType `json:"component_type" binding:"required"` + Version string `json:"version,omitempty"` + Description string `json:"description,omitempty"` + IsSafetyRelevant bool `json:"is_safety_relevant"` + IsNetworked bool `json:"is_networked"` +} + +// CreateHazardRequest is the API request for creating a new hazard +type CreateHazardRequest struct { + ProjectID uuid.UUID `json:"project_id" binding:"required"` + ComponentID uuid.UUID `json:"component_id" binding:"required"` + LibraryHazardID *uuid.UUID `json:"library_hazard_id,omitempty"` + Name string `json:"name" binding:"required"` + Description string `json:"description,omitempty"` + Scenario string `json:"scenario,omitempty"` + Category string `json:"category" binding:"required"` + SubCategory string `json:"sub_category,omitempty"` + MachineModule string `json:"machine_module,omitempty"` + Function string `json:"function,omitempty"` + LifecyclePhase string `json:"lifecycle_phase,omitempty"` + HazardousZone string `json:"hazardous_zone,omitempty"` + TriggerEvent string `json:"trigger_event,omitempty"` + AffectedPerson string `json:"affected_person,omitempty"` + PossibleHarm string `json:"possible_harm,omitempty"` +} + +// AssessRiskRequest is the API request for performing a risk assessment +type AssessRiskRequest struct { + HazardID uuid.UUID `json:"hazard_id" binding:"required"` + Severity int `json:"severity" binding:"required"` + Exposure int `json:"exposure" binding:"required"` + Probability int `json:"probability" binding:"required"` + Avoidance int `json:"avoidance,omitempty"` // 0=disabled, 1-5 (3=neutral) + ControlMaturity int `json:"control_maturity" binding:"required"` + ControlCoverage float64 `json:"control_coverage" binding:"required"` + TestEvidenceStrength float64 `json:"test_evidence_strength" binding:"required"` + AcceptanceJustification string `json:"acceptance_justification,omitempty"` +} + +// CreateMitigationRequest is the API request for creating a mitigation measure +type CreateMitigationRequest struct { + HazardID uuid.UUID `json:"hazard_id" binding:"required"` + ReductionType ReductionType `json:"reduction_type" binding:"required"` + Name string `json:"name" binding:"required"` + Description string `json:"description,omitempty"` +} + +// CreateVerificationPlanRequest is the API request for creating a verification plan +type CreateVerificationPlanRequest struct { + ProjectID uuid.UUID `json:"project_id" binding:"required"` + HazardID *uuid.UUID `json:"hazard_id,omitempty"` + MitigationID *uuid.UUID `json:"mitigation_id,omitempty"` + Title string `json:"title" binding:"required"` + Description string `json:"description,omitempty"` + AcceptanceCriteria string `json:"acceptance_criteria,omitempty"` + Method VerificationMethod `json:"method" binding:"required"` +} + +// CreateMonitoringEventRequest is the API request for logging a monitoring event +type CreateMonitoringEventRequest struct { + ProjectID uuid.UUID `json:"project_id" binding:"required"` + EventType MonitoringEventType `json:"event_type" binding:"required"` + Title string `json:"title" binding:"required"` + Description string `json:"description,omitempty"` + Severity string `json:"severity" binding:"required"` +} + +// InitFromProfileRequest is the API request for initializing a project from a company profile +type InitFromProfileRequest struct { + CompanyProfile json.RawMessage `json:"company_profile" binding:"required"` + ComplianceScope json.RawMessage `json:"compliance_scope" binding:"required"` +} + +// ============================================================================ +// API Response Types +// ============================================================================ + +// ProjectListResponse is the API response for listing projects +type ProjectListResponse struct { + Projects []Project `json:"projects"` + Total int `json:"total"` +} + +// ProjectDetailResponse is the API response for a single project with related entities +type ProjectDetailResponse struct { + Project + Components []Component `json:"components"` + Classifications []RegulatoryClassification `json:"classifications"` + CompletenessGates []CompletenessGate `json:"completeness_gates"` +} + +// RiskSummaryResponse is the API response for an aggregated risk overview +type RiskSummaryResponse struct { + TotalHazards int `json:"total_hazards"` + NotAcceptable int `json:"not_acceptable,omitempty"` + VeryHigh int `json:"very_high,omitempty"` + Critical int `json:"critical"` + High int `json:"high"` + Medium int `json:"medium"` + Low int `json:"low"` + Negligible int `json:"negligible"` + OverallRiskLevel RiskLevel `json:"overall_risk_level"` + AllAcceptable bool `json:"all_acceptable"` +} + +// LifecyclePhaseInfo represents a machine lifecycle phase with labels +type LifecyclePhaseInfo struct { + ID string `json:"id"` + LabelDE string `json:"label_de"` + LabelEN string `json:"label_en"` + Sort int `json:"sort_order"` +} + +// RoleInfo represents an affected person role with labels +type RoleInfo struct { + ID string `json:"id"` + LabelDE string `json:"label_de"` + LabelEN string `json:"label_en"` + Sort int `json:"sort_order"` +} + +// EvidenceTypeInfo represents an evidence/verification type with labels +type EvidenceTypeInfo struct { + ID string `json:"id"` + Category string `json:"category"` + LabelDE string `json:"label_de"` + LabelEN string `json:"label_en"` + Tags []string `json:"tags,omitempty"` + Sort int `json:"sort_order"` +} + +// ProtectiveMeasureEntry represents a protective measure from the library +type ProtectiveMeasureEntry struct { + ID string `json:"id"` + ReductionType string `json:"reduction_type"` + SubType string `json:"sub_type,omitempty"` + Name string `json:"name"` + Description string `json:"description"` + HazardCategory string `json:"hazard_category,omitempty"` + Examples []string `json:"examples,omitempty"` + Tags []string `json:"tags,omitempty"` +} + +// ValidateMitigationHierarchyRequest is the request for hierarchy validation +type ValidateMitigationHierarchyRequest struct { + HazardID uuid.UUID `json:"hazard_id" binding:"required"` + ReductionType ReductionType `json:"reduction_type" binding:"required"` +} + +// ValidateMitigationHierarchyResponse is the response from hierarchy validation +type ValidateMitigationHierarchyResponse struct { + Valid bool `json:"valid"` + Warnings []string `json:"warnings,omitempty"` +} + +// CompletenessGate represents a single gate in the project completeness checklist +type CompletenessGate struct { + ID string `json:"id"` + Category string `json:"category"` + Label string `json:"label"` + Required bool `json:"required"` + Passed bool `json:"passed"` + Details string `json:"details,omitempty"` +} diff --git a/ai-compliance-sdk/internal/iace/models_entities.go b/ai-compliance-sdk/internal/iace/models_entities.go new file mode 100644 index 0000000..9a0a318 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/models_entities.go @@ -0,0 +1,236 @@ +package iace + +import ( + "encoding/json" + "time" + + "github.com/google/uuid" +) + +// ============================================================================ +// Main Entities +// ============================================================================ + +// Project represents an IACE compliance project for a machine or system +type Project struct { + ID uuid.UUID `json:"id"` + TenantID uuid.UUID `json:"tenant_id"` + MachineName string `json:"machine_name"` + MachineType string `json:"machine_type"` + Manufacturer string `json:"manufacturer"` + Description string `json:"description,omitempty"` + NarrativeText string `json:"narrative_text,omitempty"` + Status ProjectStatus `json:"status"` + CEMarkingTarget string `json:"ce_marking_target,omitempty"` + CompletenessScore float64 `json:"completeness_score"` + RiskSummary map[string]int `json:"risk_summary,omitempty"` + TriggeredRegulations json.RawMessage `json:"triggered_regulations,omitempty"` + Metadata json.RawMessage `json:"metadata,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ArchivedAt *time.Time `json:"archived_at,omitempty"` +} + +// Component represents a system component within a project +type Component struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Name string `json:"name"` + ComponentType ComponentType `json:"component_type"` + Version string `json:"version,omitempty"` + Description string `json:"description,omitempty"` + IsSafetyRelevant bool `json:"is_safety_relevant"` + IsNetworked bool `json:"is_networked"` + Metadata json.RawMessage `json:"metadata,omitempty"` + SortOrder int `json:"sort_order"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// RegulatoryClassification represents the classification result for a regulation +type RegulatoryClassification struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + Regulation RegulationType `json:"regulation"` + ClassificationResult string `json:"classification_result"` + RiskLevel RiskLevel `json:"risk_level"` + Confidence float64 `json:"confidence"` + Reasoning string `json:"reasoning,omitempty"` + RAGSources json.RawMessage `json:"rag_sources,omitempty"` + Requirements json.RawMessage `json:"requirements,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// HazardLibraryEntry represents a reusable hazard template from the library +type HazardLibraryEntry struct { + ID uuid.UUID `json:"id"` + Category string `json:"category"` + SubCategory string `json:"sub_category,omitempty"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + DefaultSeverity int `json:"default_severity"` + DefaultProbability int `json:"default_probability"` + DefaultExposure int `json:"default_exposure,omitempty"` + DefaultAvoidance int `json:"default_avoidance,omitempty"` + ApplicableComponentTypes []string `json:"applicable_component_types"` + RegulationReferences []string `json:"regulation_references"` + SuggestedMitigations json.RawMessage `json:"suggested_mitigations,omitempty"` + TypicalCauses []string `json:"typical_causes,omitempty"` + TypicalHarm string `json:"typical_harm,omitempty"` + RelevantLifecyclePhases []string `json:"relevant_lifecycle_phases,omitempty"` + RecommendedMeasuresDesign []string `json:"recommended_measures_design,omitempty"` + RecommendedMeasuresTechnical []string `json:"recommended_measures_technical,omitempty"` + RecommendedMeasuresInformation []string `json:"recommended_measures_information,omitempty"` + SuggestedEvidence []string `json:"suggested_evidence,omitempty"` + RelatedKeywords []string `json:"related_keywords,omitempty"` + Tags []string `json:"tags,omitempty"` + IsBuiltin bool `json:"is_builtin"` + TenantID *uuid.UUID `json:"tenant_id,omitempty"` + CreatedAt time.Time `json:"created_at"` +} + +// Hazard represents a specific hazard identified within a project +type Hazard struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + ComponentID uuid.UUID `json:"component_id"` + LibraryHazardID *uuid.UUID `json:"library_hazard_id,omitempty"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Scenario string `json:"scenario,omitempty"` + Category string `json:"category"` + SubCategory string `json:"sub_category,omitempty"` + Status HazardStatus `json:"status"` + MachineModule string `json:"machine_module,omitempty"` + Function string `json:"function,omitempty"` + LifecyclePhase string `json:"lifecycle_phase,omitempty"` + HazardousZone string `json:"hazardous_zone,omitempty"` + TriggerEvent string `json:"trigger_event,omitempty"` + AffectedPerson string `json:"affected_person,omitempty"` + PossibleHarm string `json:"possible_harm,omitempty"` + ReviewStatus ReviewStatus `json:"review_status,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// RiskAssessment represents a quantitative risk assessment for a hazard +type RiskAssessment struct { + ID uuid.UUID `json:"id"` + HazardID uuid.UUID `json:"hazard_id"` + Version int `json:"version"` + AssessmentType AssessmentType `json:"assessment_type"` + Severity int `json:"severity"` + Exposure int `json:"exposure"` + Probability int `json:"probability"` + Avoidance int `json:"avoidance,omitempty"` // 0=disabled, 1-5 (3=neutral) + InherentRisk float64 `json:"inherent_risk"` + ControlMaturity int `json:"control_maturity"` + ControlCoverage float64 `json:"control_coverage"` + TestEvidenceStrength float64 `json:"test_evidence_strength"` + CEff float64 `json:"c_eff"` + ResidualRisk float64 `json:"residual_risk"` + RiskLevel RiskLevel `json:"risk_level"` + IsAcceptable bool `json:"is_acceptable"` + AcceptanceJustification string `json:"acceptance_justification,omitempty"` + AssessedBy uuid.UUID `json:"assessed_by"` + CreatedAt time.Time `json:"created_at"` +} + +// Mitigation represents a risk reduction measure applied to a hazard +type Mitigation struct { + ID uuid.UUID `json:"id"` + HazardID uuid.UUID `json:"hazard_id"` + ReductionType ReductionType `json:"reduction_type"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Status MitigationStatus `json:"status"` + VerificationMethod VerificationMethod `json:"verification_method,omitempty"` + VerificationResult string `json:"verification_result,omitempty"` + VerifiedAt *time.Time `json:"verified_at,omitempty"` + VerifiedBy uuid.UUID `json:"verified_by,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// Evidence represents an uploaded file that serves as evidence for compliance +type Evidence struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + MitigationID *uuid.UUID `json:"mitigation_id,omitempty"` + VerificationPlanID *uuid.UUID `json:"verification_plan_id,omitempty"` + FileName string `json:"file_name"` + FilePath string `json:"file_path"` + FileHash string `json:"file_hash"` + FileSize int64 `json:"file_size"` + MimeType string `json:"mime_type"` + Description string `json:"description,omitempty"` + UploadedBy uuid.UUID `json:"uploaded_by"` + CreatedAt time.Time `json:"created_at"` +} + +// VerificationPlan represents a plan for verifying compliance measures +type VerificationPlan struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + HazardID *uuid.UUID `json:"hazard_id,omitempty"` + MitigationID *uuid.UUID `json:"mitigation_id,omitempty"` + Title string `json:"title"` + Description string `json:"description,omitempty"` + AcceptanceCriteria string `json:"acceptance_criteria,omitempty"` + Method VerificationMethod `json:"method"` + Status string `json:"status"` + Result string `json:"result,omitempty"` + CompletedAt *time.Time `json:"completed_at,omitempty"` + CompletedBy uuid.UUID `json:"completed_by,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// TechFileSection represents a section of the technical documentation file +type TechFileSection struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + SectionType string `json:"section_type"` + Title string `json:"title"` + Content string `json:"content,omitempty"` + Version int `json:"version"` + Status TechFileSectionStatus `json:"status"` + ApprovedBy uuid.UUID `json:"approved_by,omitempty"` + ApprovedAt *time.Time `json:"approved_at,omitempty"` + Metadata json.RawMessage `json:"metadata,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// MonitoringEvent represents a post-market monitoring event +type MonitoringEvent struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + EventType MonitoringEventType `json:"event_type"` + Title string `json:"title"` + Description string `json:"description,omitempty"` + Severity string `json:"severity"` + ImpactAssessment string `json:"impact_assessment,omitempty"` + Status string `json:"status"` + ResolvedAt *time.Time `json:"resolved_at,omitempty"` + ResolvedBy uuid.UUID `json:"resolved_by,omitempty"` + Metadata json.RawMessage `json:"metadata,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// AuditTrailEntry represents an immutable audit log entry for compliance traceability +type AuditTrailEntry struct { + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"project_id"` + EntityType string `json:"entity_type"` + EntityID uuid.UUID `json:"entity_id"` + Action AuditAction `json:"action"` + UserID uuid.UUID `json:"user_id"` + OldValues json.RawMessage `json:"old_values,omitempty"` + NewValues json.RawMessage `json:"new_values,omitempty"` + Hash string `json:"hash"` + CreatedAt time.Time `json:"created_at"` +} diff --git a/ai-compliance-sdk/internal/iace/tech_file_generator.go b/ai-compliance-sdk/internal/iace/tech_file_generator.go index 45b95f2..1c7627c 100644 --- a/ai-compliance-sdk/internal/iace/tech_file_generator.go +++ b/ai-compliance-sdk/internal/iace/tech_file_generator.go @@ -42,109 +42,6 @@ type SectionGenerationContext struct { RAGContext string // aggregated text from RAG search } -// ============================================================================ -// Section type constants -// ============================================================================ - -const ( - SectionRiskAssessmentReport = "risk_assessment_report" - SectionHazardLogCombined = "hazard_log_combined" - SectionGeneralDescription = "general_description" - SectionEssentialRequirements = "essential_requirements" - SectionDesignSpecifications = "design_specifications" - SectionTestReports = "test_reports" - SectionStandardsApplied = "standards_applied" - SectionDeclarationConformity = "declaration_of_conformity" - SectionAIIntendedPurpose = "ai_intended_purpose" - SectionAIModelDescription = "ai_model_description" - SectionAIRiskManagement = "ai_risk_management" - SectionAIHumanOversight = "ai_human_oversight" - SectionComponentList = "component_list" - SectionClassificationReport = "classification_report" - SectionMitigationReport = "mitigation_report" - SectionVerificationReport = "verification_report" - SectionEvidenceIndex = "evidence_index" - SectionInstructionsForUse = "instructions_for_use" - SectionMonitoringPlan = "monitoring_plan" -) - -// ============================================================================ -// System prompts (German — CE compliance context) -// ============================================================================ - -var sectionSystemPrompts = map[string]string{ - SectionRiskAssessmentReport: `Du bist CE-Experte fuer Maschinen- und KI-Sicherheit. Erstelle eine strukturierte Zusammenfassung der Risikobeurteilung gemaess ISO 12100 und EN ISO 13849. Gliederung: 1) Methodik, 2) Risikoueberblick (Anzahl Gefaehrdungen nach Risikostufe), 3) Kritische Risiken, 4) Akzeptanzbewertung, 5) Empfehlungen. Verwende Fachterminologie und beziehe dich auf die konkreten Projektdaten.`, - - SectionHazardLogCombined: `Erstelle ein tabellarisches Gefaehrdungsprotokoll (Hazard Log) fuer die technische Dokumentation. Jede Gefaehrdung soll enthalten: ID, Bezeichnung, Kategorie, Lebenszyklusphase, Szenario, Schwere, Eintrittswahrscheinlichkeit, Risikolevel, Massnahmen und Status. Formatiere als strukturierte Tabelle in Markdown.`, - - SectionGeneralDescription: `Erstelle eine allgemeine Maschinenbeschreibung fuer die technische Dokumentation gemaess EU-Maschinenverordnung 2023/1230 Anhang IV. Beschreibe: 1) Bestimmungsgemaesse Verwendung, 2) Aufbau und Funktion, 3) Systemkomponenten, 4) Betriebsbedingungen, 5) Schnittstellen. Verwende die bereitgestellten Projektdaten.`, - - SectionEssentialRequirements: `Beschreibe die anwendbaren grundlegenden Anforderungen (Essential Health and Safety Requirements — EHSR) gemaess EU-Maschinenverordnung 2023/1230 Anhang III. Ordne jede Anforderung den relevanten Gefaehrdungen und Massnahmen zu. Beruecksichtige auch AI Act und CRA Anforderungen falls KI-Komponenten vorhanden sind.`, - - SectionDesignSpecifications: `Erstelle eine Uebersicht der Konstruktionsdaten und Spezifikationen fuer die technische Dokumentation. Enthalten sein sollen: 1) Systemarchitektur, 2) Komponentenliste mit Sicherheitsrelevanz, 3) Software-/Firmware-Versionen, 4) Schnittstellenbeschreibungen, 5) Sicherheitsfunktionen. Beziehe dich auf die konkreten Komponenten.`, - - SectionTestReports: `Erstelle eine Zusammenfassung der Pruefberichte und Verifikationsergebnisse. Gliederung: 1) Durchgefuehrte Pruefungen, 2) Pruefmethoden (Test, Analyse, Inspektion), 3) Ergebnisse pro Massnahme, 4) Offene Punkte, 5) Gesamtbewertung. Referenziere die konkreten Mitigationsmassnahmen und deren Verifikationsstatus.`, - - SectionStandardsApplied: `Liste die angewandten harmonisierten Normen und technischen Spezifikationen auf. Ordne jede Norm den relevanten Anforderungen und Gefaehrdungskategorien zu. Beruecksichtige: ISO 12100, ISO 13849, IEC 62443, ISO/IEC 27001, sowie branchenspezifische Normen. Erklaere die Vermutungswirkung (Presumption of Conformity).`, - - SectionDeclarationConformity: `Erstelle eine EU-Konformitaetserklaerung nach EU-Maschinenverordnung 2023/1230 Anhang IV. Enthalten sein muessen: 1) Hersteller-Angaben, 2) Produktidentifikation, 3) Angewandte Richtlinien und Verordnungen, 4) Angewandte Normen, 5) Bevollmaechtigter, 6) Ort, Datum, Unterschrift. Formales Dokument-Layout.`, - - SectionAIIntendedPurpose: `Beschreibe den bestimmungsgemaessen Zweck des KI-Systems gemaess AI Act Art. 13 (Transparenzpflichten). Enthalten sein sollen: 1) Zweckbestimmung, 2) Einsatzbereich und -grenzen, 3) Zielgruppe, 4) Vorhersehbarer Fehlgebrauch, 5) Leistungskennzahlen, 6) Einschraenkungen und bekannte Risiken.`, - - SectionAIModelDescription: `Beschreibe das KI-Modell, die Trainingsdaten und die Architektur gemaess AI Act Anhang IV. Enthalten: 1) Modelltyp und Architektur, 2) Trainingsdaten (Herkunft, Umfang, Qualitaet), 3) Validierungsmethodik, 4) Leistungsmetriken, 5) Bekannte Verzerrungen (Bias), 6) Energie-/Ressourcenverbrauch.`, - - SectionAIRiskManagement: `Erstelle eine Beschreibung des KI-Risikomanagementsystems gemaess AI Act Art. 9. Gliederung: 1) Risikomanagement-Prozess, 2) Identifizierte Risiken fuer Gesundheit/Sicherheit/Grundrechte, 3) Risikomindernde Massnahmen, 4) Restrisiken, 5) Ueberwachungs- und Aktualisierungsverfahren.`, - - SectionAIHumanOversight: `Beschreibe die Massnahmen zur menschlichen Aufsicht (Human Oversight) gemaess AI Act Art. 14. Enthalten: 1) Aufsichtskonzept, 2) Rollen und Verantwortlichkeiten, 3) Eingriffsmoglichkeiten, 4) Uebersteuern/Abschalten, 5) Schulungsanforderungen, 6) Informationspflichten an Nutzer.`, - - SectionComponentList: `Erstelle eine detaillierte Komponentenliste fuer die technische Dokumentation. Pro Komponente: Name, Typ, Version, Beschreibung, Sicherheitsrelevanz, Vernetzungsstatus. Kennzeichne sicherheitsrelevante und vernetzte Komponenten besonders. Gruppiere nach Komponententyp.`, - - SectionClassificationReport: `Erstelle einen Klassifizierungsbericht, der die regulatorische Einordnung des Produkts zusammenfasst. Pro Verordnung (MVO, AI Act, CRA, NIS2): Klassifizierungsergebnis, Risikoklasse, Begruendung, daraus resultierende Anforderungen. Bewerte die Gesamtkonformitaetslage.`, - - SectionMitigationReport: `Erstelle einen Massnahmenbericht (Mitigation Report) fuer die technische Dokumentation. Gliederung nach 3-Stufen-Methode: 1) Inhaerent sichere Konstruktion (Design), 2) Technische Schutzmassnahmen (Protective), 3) Benutzerinformation (Information). Pro Massnahme: Status, Verifikation, zugeordnete Gefaehrdung.`, - - SectionVerificationReport: `Erstelle einen Verifikationsbericht ueber alle durchgefuehrten Pruef- und Nachweisverfahren. Enthalten: 1) Verifikationsplan-Uebersicht, 2) Durchgefuehrte Pruefungen nach Methode, 3) Ergebnisse und Bewertung, 4) Offene Verifikationen, 5) Gesamtstatus der Konformitaetsnachweise.`, - - SectionEvidenceIndex: `Erstelle ein Nachweisverzeichnis (Evidence Index) fuer die technische Dokumentation. Liste alle vorhandenen Nachweisdokumente auf: Dateiname, Beschreibung, zugeordnete Massnahme, Dokumenttyp. Identifiziere fehlende Nachweise und empfehle Ergaenzungen.`, - - SectionInstructionsForUse: `Erstelle eine Gliederung fuer die Betriebsanleitung gemaess EU-Maschinenverordnung 2023/1230 Anhang III Abschnitt 1.7.4. Enthalten: 1) Bestimmungsgemaesse Verwendung, 2) Inbetriebnahme, 3) Sicherer Betrieb, 4) Wartung, 5) Restrisiken und Warnhinweise, 6) Ausserbetriebnahme. Beruecksichtige identifizierte Gefaehrdungen.`, - - SectionMonitoringPlan: `Erstelle einen Post-Market-Monitoring-Plan fuer das Produkt. Enthalten: 1) Ueberwachungsziele, 2) Datenquellen (Kundenfeedback, Vorfaelle, Updates), 3) Ueberwachungsintervalle, 4) Eskalationsverfahren, 5) Dokumentationspflichten, 6) Verantwortlichkeiten. Beruecksichtige AI Act Art. 72 (Post-Market Monitoring) falls KI-Komponenten vorhanden.`, -} - -// ============================================================================ -// RAG query mapping -// ============================================================================ - -func buildRAGQuery(sectionType string) string { - ragQueries := map[string]string{ - SectionRiskAssessmentReport: "Risikobeurteilung ISO 12100 Risikobewertung Maschine Gefaehrdungsanalyse", - SectionHazardLogCombined: "Gefaehrdungsprotokoll Hazard Log Risikoanalyse Gefaehrdungsidentifikation", - SectionGeneralDescription: "Maschinenbeschreibung technische Dokumentation bestimmungsgemaesse Verwendung", - SectionEssentialRequirements: "grundlegende Anforderungen EHSR Maschinenverordnung Anhang III Sicherheitsanforderungen", - SectionDesignSpecifications: "Konstruktionsdaten Spezifikationen Systemarchitektur technische Dokumentation", - SectionTestReports: "Pruefberichte Verifikation Validierung Konformitaetsbewertung Testberichte", - SectionStandardsApplied: "harmonisierte Normen ISO 12100 ISO 13849 IEC 62443 Vermutungswirkung", - SectionDeclarationConformity: "EU-Konformitaetserklaerung Maschinenverordnung 2023/1230 Anhang IV CE-Kennzeichnung", - SectionAIIntendedPurpose: "bestimmungsgemaesser Zweck KI-System AI Act Art. 13 Transparenz Intended Purpose", - SectionAIModelDescription: "KI-Modell Trainingsdaten Architektur AI Act Anhang IV technische Dokumentation", - SectionAIRiskManagement: "KI-Risikomanagementsystem AI Act Art. 9 Risikomanagement kuenstliche Intelligenz", - SectionAIHumanOversight: "menschliche Aufsicht Human Oversight AI Act Art. 14 Kontrolle KI-System", - SectionComponentList: "Komponentenliste Systemkomponenten sicherheitsrelevante Bauteile technische Dokumentation", - SectionClassificationReport: "regulatorische Klassifizierung Risikoklasse AI Act CRA Maschinenverordnung", - SectionMitigationReport: "Risikomindernde Massnahmen 3-Stufen-Methode ISO 12100 Schutzmassnahmen", - SectionVerificationReport: "Verifikation Validierung Pruefnachweis Konformitaetsbewertung Pruefprotokoll", - SectionEvidenceIndex: "Nachweisdokumente Evidence Konformitaetsnachweis Dokumentenindex", - SectionInstructionsForUse: "Betriebsanleitung Benutzerinformation Maschinenverordnung Abschnitt 1.7.4 Sicherheitshinweise", - SectionMonitoringPlan: "Post-Market-Monitoring Ueberwachungsplan AI Act Art. 72 Marktbeobachtung", - } - - if q, ok := ragQueries[sectionType]; ok { - return q - } - return "CE-Konformitaet technische Dokumentation Maschinenverordnung AI Act" -} - // ============================================================================ // BuildSectionContext — loads all project data + RAG context // ============================================================================ @@ -225,7 +122,7 @@ func (g *TechFileGenerator) BuildSectionContext(ctx context.Context, projectID u Mitigations: mitigations, Classifications: classifications, Evidence: evidence, - RAGContext: ragContext, + RAGContext: ragContext, }, nil } @@ -261,419 +158,3 @@ func (g *TechFileGenerator) GenerateSection(ctx context.Context, projectID uuid. return resp.Message.Content, nil } - -// ============================================================================ -// Prompt builders -// ============================================================================ - -func getSystemPrompt(sectionType string) string { - if prompt, ok := sectionSystemPrompts[sectionType]; ok { - return prompt - } - return "Du bist CE-Experte fuer technische Dokumentation. Erstelle den angeforderten Abschnitt der technischen Dokumentation basierend auf den bereitgestellten Projektdaten. Schreibe auf Deutsch, verwende Fachterminologie und beziehe dich auf die konkreten Daten." -} - -func buildUserPrompt(sctx *SectionGenerationContext, sectionType string) string { - var b strings.Builder - - if sctx == nil || sctx.Project == nil { - b.WriteString("## Maschine / System\n\n- Keine Projektdaten vorhanden.\n\n") - return b.String() - } - - // Machine info — always included - b.WriteString("## Maschine / System\n\n") - b.WriteString(fmt.Sprintf("- **Name:** %s\n", sctx.Project.MachineName)) - b.WriteString(fmt.Sprintf("- **Typ:** %s\n", sctx.Project.MachineType)) - b.WriteString(fmt.Sprintf("- **Hersteller:** %s\n", sctx.Project.Manufacturer)) - if sctx.Project.Description != "" { - b.WriteString(fmt.Sprintf("- **Beschreibung:** %s\n", sctx.Project.Description)) - } - if sctx.Project.CEMarkingTarget != "" { - b.WriteString(fmt.Sprintf("- **CE-Kennzeichnungsziel:** %s\n", sctx.Project.CEMarkingTarget)) - } - if sctx.Project.NarrativeText != "" { - b.WriteString(fmt.Sprintf("\n**Projektbeschreibung:** %s\n", truncateForPrompt(sctx.Project.NarrativeText, 500))) - } - b.WriteString("\n") - - // Components — for most section types - if len(sctx.Components) > 0 && needsComponents(sectionType) { - b.WriteString("## Komponenten\n\n") - for i, c := range sctx.Components { - if i >= 20 { - b.WriteString(fmt.Sprintf("... und %d weitere Komponenten\n", len(sctx.Components)-20)) - break - } - safety := "" - if c.IsSafetyRelevant { - safety = " [SICHERHEITSRELEVANT]" - } - networked := "" - if c.IsNetworked { - networked = " [VERNETZT]" - } - b.WriteString(fmt.Sprintf("- %s (Typ: %s)%s%s", c.Name, string(c.ComponentType), safety, networked)) - if c.Description != "" { - b.WriteString(fmt.Sprintf(" — %s", truncateForPrompt(c.Description, 100))) - } - b.WriteString("\n") - } - b.WriteString("\n") - } - - // Hazards + assessments — for risk-related sections - if len(sctx.Hazards) > 0 && needsHazards(sectionType) { - b.WriteString("## Gefaehrdungen und Risikobewertungen\n\n") - for i, h := range sctx.Hazards { - if i >= 30 { - b.WriteString(fmt.Sprintf("... und %d weitere Gefaehrdungen\n", len(sctx.Hazards)-30)) - break - } - b.WriteString(fmt.Sprintf("### %s\n", h.Name)) - b.WriteString(fmt.Sprintf("- Kategorie: %s", h.Category)) - if h.SubCategory != "" { - b.WriteString(fmt.Sprintf(" / %s", h.SubCategory)) - } - b.WriteString("\n") - if h.LifecyclePhase != "" { - b.WriteString(fmt.Sprintf("- Lebenszyklusphase: %s\n", h.LifecyclePhase)) - } - if h.Scenario != "" { - b.WriteString(fmt.Sprintf("- Szenario: %s\n", truncateForPrompt(h.Scenario, 150))) - } - if h.PossibleHarm != "" { - b.WriteString(fmt.Sprintf("- Moeglicher Schaden: %s\n", h.PossibleHarm)) - } - if h.AffectedPerson != "" { - b.WriteString(fmt.Sprintf("- Betroffene Person: %s\n", h.AffectedPerson)) - } - b.WriteString(fmt.Sprintf("- Status: %s\n", string(h.Status))) - - // Latest assessment - if assessments, ok := sctx.Assessments[h.ID]; ok && len(assessments) > 0 { - a := assessments[len(assessments)-1] // latest - b.WriteString(fmt.Sprintf("- Bewertung: S=%d E=%d P=%d → Risiko=%.1f (%s) %s\n", - a.Severity, a.Exposure, a.Probability, - a.ResidualRisk, string(a.RiskLevel), - acceptableLabel(a.IsAcceptable))) - } - b.WriteString("\n") - } - } - - // Mitigations — for mitigation/verification sections - if needsMitigations(sectionType) { - designMeasures, protectiveMeasures, infoMeasures := groupMitigations(sctx) - if len(designMeasures)+len(protectiveMeasures)+len(infoMeasures) > 0 { - b.WriteString("## Risikomindernde Massnahmen (3-Stufen-Methode)\n\n") - writeMitigationGroup(&b, "Stufe 1: Inhaerent sichere Konstruktion (Design)", designMeasures) - writeMitigationGroup(&b, "Stufe 2: Technische Schutzmassnahmen (Protective)", protectiveMeasures) - writeMitigationGroup(&b, "Stufe 3: Benutzerinformation (Information)", infoMeasures) - } - } - - // Classifications — for classification/standards sections - if len(sctx.Classifications) > 0 && needsClassifications(sectionType) { - b.WriteString("## Regulatorische Klassifizierungen\n\n") - for _, c := range sctx.Classifications { - b.WriteString(fmt.Sprintf("- **%s:** %s (Risiko: %s)\n", - string(c.Regulation), c.ClassificationResult, string(c.RiskLevel))) - if c.Reasoning != "" { - b.WriteString(fmt.Sprintf(" Begruendung: %s\n", truncateForPrompt(c.Reasoning, 200))) - } - } - b.WriteString("\n") - } - - // Evidence — for evidence/verification sections - if len(sctx.Evidence) > 0 && needsEvidence(sectionType) { - b.WriteString("## Vorhandene Nachweise\n\n") - for i, e := range sctx.Evidence { - if i >= 30 { - b.WriteString(fmt.Sprintf("... und %d weitere Nachweise\n", len(sctx.Evidence)-30)) - break - } - b.WriteString(fmt.Sprintf("- %s", e.FileName)) - if e.Description != "" { - b.WriteString(fmt.Sprintf(" — %s", truncateForPrompt(e.Description, 100))) - } - b.WriteString("\n") - } - b.WriteString("\n") - } - - // RAG context — if available - if sctx.RAGContext != "" { - b.WriteString("## Relevante Rechtsgrundlagen (RAG)\n\n") - b.WriteString(sctx.RAGContext) - b.WriteString("\n\n") - } - - // Instruction - b.WriteString("---\n\n") - b.WriteString("Erstelle den Abschnitt basierend auf den obigen Daten. Schreibe auf Deutsch, verwende Markdown-Formatierung und beziehe dich auf die konkreten Projektdaten.\n") - - return b.String() -} - -// ============================================================================ -// Section type → data requirements -// ============================================================================ - -func needsComponents(sectionType string) bool { - switch sectionType { - case SectionGeneralDescription, SectionDesignSpecifications, SectionComponentList, - SectionEssentialRequirements, SectionAIModelDescription, SectionAIIntendedPurpose, - SectionClassificationReport, SectionInstructionsForUse: - return true - } - return false -} - -func needsHazards(sectionType string) bool { - switch sectionType { - case SectionRiskAssessmentReport, SectionHazardLogCombined, SectionEssentialRequirements, - SectionMitigationReport, SectionVerificationReport, SectionTestReports, - SectionAIRiskManagement, SectionInstructionsForUse, SectionMonitoringPlan: - return true - } - return false -} - -func needsMitigations(sectionType string) bool { - switch sectionType { - case SectionRiskAssessmentReport, SectionMitigationReport, SectionVerificationReport, - SectionTestReports, SectionEssentialRequirements, SectionAIRiskManagement, - SectionAIHumanOversight, SectionInstructionsForUse: - return true - } - return false -} - -func needsClassifications(sectionType string) bool { - switch sectionType { - case SectionClassificationReport, SectionEssentialRequirements, SectionStandardsApplied, - SectionDeclarationConformity, SectionAIIntendedPurpose, SectionAIRiskManagement, - SectionGeneralDescription: - return true - } - return false -} - -func needsEvidence(sectionType string) bool { - switch sectionType { - case SectionEvidenceIndex, SectionVerificationReport, SectionTestReports, - SectionMitigationReport: - return true - } - return false -} - -// ============================================================================ -// Mitigation grouping helper -// ============================================================================ - -func groupMitigations(sctx *SectionGenerationContext) (design, protective, info []Mitigation) { - for _, mits := range sctx.Mitigations { - for _, m := range mits { - switch m.ReductionType { - case ReductionTypeDesign: - design = append(design, m) - case ReductionTypeProtective: - protective = append(protective, m) - case ReductionTypeInformation: - info = append(info, m) - } - } - } - return -} - -func writeMitigationGroup(b *strings.Builder, title string, measures []Mitigation) { - if len(measures) == 0 { - return - } - b.WriteString(fmt.Sprintf("### %s\n\n", title)) - for i, m := range measures { - if i >= 20 { - b.WriteString(fmt.Sprintf("... und %d weitere Massnahmen\n", len(measures)-20)) - break - } - b.WriteString(fmt.Sprintf("- **%s** [%s]", m.Name, string(m.Status))) - if m.VerificationMethod != "" { - b.WriteString(fmt.Sprintf(" — Verifikation: %s", string(m.VerificationMethod))) - if m.VerificationResult != "" { - b.WriteString(fmt.Sprintf(" (%s)", m.VerificationResult)) - } - } - b.WriteString("\n") - if m.Description != "" { - b.WriteString(fmt.Sprintf(" %s\n", truncateForPrompt(m.Description, 150))) - } - } - b.WriteString("\n") -} - -// ============================================================================ -// Fallback content (when LLM is unavailable) -// ============================================================================ - -func buildFallbackContent(sctx *SectionGenerationContext, sectionType string) string { - var b strings.Builder - - b.WriteString("[Automatisch generiert — LLM nicht verfuegbar]\n\n") - - sectionTitle := sectionDisplayName(sectionType) - b.WriteString(fmt.Sprintf("# %s\n\n", sectionTitle)) - - b.WriteString(fmt.Sprintf("**Maschine:** %s (%s)\n", sctx.Project.MachineName, sctx.Project.MachineType)) - b.WriteString(fmt.Sprintf("**Hersteller:** %s\n", sctx.Project.Manufacturer)) - if sctx.Project.Description != "" { - b.WriteString(fmt.Sprintf("**Beschreibung:** %s\n", sctx.Project.Description)) - } - b.WriteString("\n") - - // Section-specific data summaries - switch sectionType { - case SectionComponentList, SectionGeneralDescription, SectionDesignSpecifications: - if len(sctx.Components) > 0 { - b.WriteString("## Komponenten\n\n") - b.WriteString(fmt.Sprintf("Anzahl: %d\n\n", len(sctx.Components))) - for _, c := range sctx.Components { - safety := "" - if c.IsSafetyRelevant { - safety = " [SICHERHEITSRELEVANT]" - } - b.WriteString(fmt.Sprintf("- %s (Typ: %s)%s\n", c.Name, string(c.ComponentType), safety)) - } - b.WriteString("\n") - } - - case SectionRiskAssessmentReport, SectionHazardLogCombined: - b.WriteString("## Risikoueberblick\n\n") - b.WriteString(fmt.Sprintf("Anzahl Gefaehrdungen: %d\n\n", len(sctx.Hazards))) - riskCounts := countRiskLevels(sctx) - for level, count := range riskCounts { - b.WriteString(fmt.Sprintf("- %s: %d\n", level, count)) - } - b.WriteString("\n") - for _, h := range sctx.Hazards { - b.WriteString(fmt.Sprintf("- **%s** (%s) — Status: %s\n", h.Name, h.Category, string(h.Status))) - } - b.WriteString("\n") - - case SectionMitigationReport: - design, protective, info := groupMitigations(sctx) - total := len(design) + len(protective) + len(info) - b.WriteString("## Massnahmenueberblick\n\n") - b.WriteString(fmt.Sprintf("Gesamt: %d Massnahmen\n", total)) - b.WriteString(fmt.Sprintf("- Design: %d\n- Schutzmassnahmen: %d\n- Benutzerinformation: %d\n\n", len(design), len(protective), len(info))) - writeFallbackMitigationList(&b, "Design", design) - writeFallbackMitigationList(&b, "Schutzmassnahmen", protective) - writeFallbackMitigationList(&b, "Benutzerinformation", info) - - case SectionClassificationReport: - if len(sctx.Classifications) > 0 { - b.WriteString("## Klassifizierungen\n\n") - for _, c := range sctx.Classifications { - b.WriteString(fmt.Sprintf("- **%s:** %s (Risiko: %s)\n", - string(c.Regulation), c.ClassificationResult, string(c.RiskLevel))) - } - b.WriteString("\n") - } - - case SectionEvidenceIndex: - b.WriteString("## Nachweisverzeichnis\n\n") - b.WriteString(fmt.Sprintf("Anzahl Nachweise: %d\n\n", len(sctx.Evidence))) - for _, e := range sctx.Evidence { - desc := e.Description - if desc == "" { - desc = "(keine Beschreibung)" - } - b.WriteString(fmt.Sprintf("- %s — %s\n", e.FileName, desc)) - } - b.WriteString("\n") - - default: - // Generic fallback data summary - b.WriteString(fmt.Sprintf("- Komponenten: %d\n", len(sctx.Components))) - b.WriteString(fmt.Sprintf("- Gefaehrdungen: %d\n", len(sctx.Hazards))) - b.WriteString(fmt.Sprintf("- Klassifizierungen: %d\n", len(sctx.Classifications))) - b.WriteString(fmt.Sprintf("- Nachweise: %d\n", len(sctx.Evidence))) - b.WriteString("\n") - } - - b.WriteString("---\n") - b.WriteString("*Dieser Abschnitt wurde ohne LLM-Unterstuetzung erstellt und enthaelt nur eine Datenuebersicht. Bitte erneut generieren, wenn der LLM-Service verfuegbar ist.*\n") - - return b.String() -} - -func writeFallbackMitigationList(b *strings.Builder, title string, measures []Mitigation) { - if len(measures) == 0 { - return - } - b.WriteString(fmt.Sprintf("### %s\n\n", title)) - for _, m := range measures { - b.WriteString(fmt.Sprintf("- %s [%s]\n", m.Name, string(m.Status))) - } - b.WriteString("\n") -} - -// ============================================================================ -// Utility helpers -// ============================================================================ - -func countRiskLevels(sctx *SectionGenerationContext) map[string]int { - counts := make(map[string]int) - for _, h := range sctx.Hazards { - if assessments, ok := sctx.Assessments[h.ID]; ok && len(assessments) > 0 { - latest := assessments[len(assessments)-1] - counts[string(latest.RiskLevel)]++ - } - } - return counts -} - -func acceptableLabel(isAcceptable bool) string { - if isAcceptable { - return "[AKZEPTABEL]" - } - return "[NICHT AKZEPTABEL]" -} - -func sectionDisplayName(sectionType string) string { - names := map[string]string{ - SectionRiskAssessmentReport: "Zusammenfassung der Risikobeurteilung", - SectionHazardLogCombined: "Gefaehrdungsprotokoll (Hazard Log)", - SectionGeneralDescription: "Allgemeine Maschinenbeschreibung", - SectionEssentialRequirements: "Grundlegende Anforderungen (EHSR)", - SectionDesignSpecifications: "Konstruktionsdaten und Spezifikationen", - SectionTestReports: "Pruefberichte", - SectionStandardsApplied: "Angewandte Normen", - SectionDeclarationConformity: "EU-Konformitaetserklaerung", - SectionAIIntendedPurpose: "Bestimmungsgemaesser Zweck (KI)", - SectionAIModelDescription: "KI-Modellbeschreibung", - SectionAIRiskManagement: "KI-Risikomanagementsystem", - SectionAIHumanOversight: "Menschliche Aufsicht (Human Oversight)", - SectionComponentList: "Komponentenliste", - SectionClassificationReport: "Klassifizierungsbericht", - SectionMitigationReport: "Massnahmenbericht", - SectionVerificationReport: "Verifikationsbericht", - SectionEvidenceIndex: "Nachweisverzeichnis", - SectionInstructionsForUse: "Betriebsanleitung (Gliederung)", - SectionMonitoringPlan: "Post-Market-Monitoring-Plan", - } - if name, ok := names[sectionType]; ok { - return name - } - return sectionType -} - -func truncateForPrompt(text string, maxLen int) string { - if len(text) <= maxLen { - return text - } - return text[:maxLen] + "..." -} diff --git a/ai-compliance-sdk/internal/iace/tech_file_generator_fallback.go b/ai-compliance-sdk/internal/iace/tech_file_generator_fallback.go new file mode 100644 index 0000000..9305c1c --- /dev/null +++ b/ai-compliance-sdk/internal/iace/tech_file_generator_fallback.go @@ -0,0 +1,141 @@ +package iace + +import ( + "fmt" + "strings" +) + +// ============================================================================ +// Fallback content (when LLM is unavailable) +// ============================================================================ + +func buildFallbackContent(sctx *SectionGenerationContext, sectionType string) string { + var b strings.Builder + + b.WriteString("[Automatisch generiert — LLM nicht verfuegbar]\n\n") + + sectionTitle := sectionDisplayName(sectionType) + b.WriteString(fmt.Sprintf("# %s\n\n", sectionTitle)) + + b.WriteString(fmt.Sprintf("**Maschine:** %s (%s)\n", sctx.Project.MachineName, sctx.Project.MachineType)) + b.WriteString(fmt.Sprintf("**Hersteller:** %s\n", sctx.Project.Manufacturer)) + if sctx.Project.Description != "" { + b.WriteString(fmt.Sprintf("**Beschreibung:** %s\n", sctx.Project.Description)) + } + b.WriteString("\n") + + // Section-specific data summaries + switch sectionType { + case SectionComponentList, SectionGeneralDescription, SectionDesignSpecifications: + if len(sctx.Components) > 0 { + b.WriteString("## Komponenten\n\n") + b.WriteString(fmt.Sprintf("Anzahl: %d\n\n", len(sctx.Components))) + for _, c := range sctx.Components { + safety := "" + if c.IsSafetyRelevant { + safety = " [SICHERHEITSRELEVANT]" + } + b.WriteString(fmt.Sprintf("- %s (Typ: %s)%s\n", c.Name, string(c.ComponentType), safety)) + } + b.WriteString("\n") + } + + case SectionRiskAssessmentReport, SectionHazardLogCombined: + b.WriteString("## Risikoueberblick\n\n") + b.WriteString(fmt.Sprintf("Anzahl Gefaehrdungen: %d\n\n", len(sctx.Hazards))) + riskCounts := countRiskLevels(sctx) + for level, count := range riskCounts { + b.WriteString(fmt.Sprintf("- %s: %d\n", level, count)) + } + b.WriteString("\n") + for _, h := range sctx.Hazards { + b.WriteString(fmt.Sprintf("- **%s** (%s) — Status: %s\n", h.Name, h.Category, string(h.Status))) + } + b.WriteString("\n") + + case SectionMitigationReport: + design, protective, info := groupMitigations(sctx) + total := len(design) + len(protective) + len(info) + b.WriteString("## Massnahmenueberblick\n\n") + b.WriteString(fmt.Sprintf("Gesamt: %d Massnahmen\n", total)) + b.WriteString(fmt.Sprintf("- Design: %d\n- Schutzmassnahmen: %d\n- Benutzerinformation: %d\n\n", len(design), len(protective), len(info))) + writeFallbackMitigationList(&b, "Design", design) + writeFallbackMitigationList(&b, "Schutzmassnahmen", protective) + writeFallbackMitigationList(&b, "Benutzerinformation", info) + + case SectionClassificationReport: + if len(sctx.Classifications) > 0 { + b.WriteString("## Klassifizierungen\n\n") + for _, c := range sctx.Classifications { + b.WriteString(fmt.Sprintf("- **%s:** %s (Risiko: %s)\n", + string(c.Regulation), c.ClassificationResult, string(c.RiskLevel))) + } + b.WriteString("\n") + } + + case SectionEvidenceIndex: + b.WriteString("## Nachweisverzeichnis\n\n") + b.WriteString(fmt.Sprintf("Anzahl Nachweise: %d\n\n", len(sctx.Evidence))) + for _, e := range sctx.Evidence { + desc := e.Description + if desc == "" { + desc = "(keine Beschreibung)" + } + b.WriteString(fmt.Sprintf("- %s — %s\n", e.FileName, desc)) + } + b.WriteString("\n") + + default: + // Generic fallback data summary + b.WriteString(fmt.Sprintf("- Komponenten: %d\n", len(sctx.Components))) + b.WriteString(fmt.Sprintf("- Gefaehrdungen: %d\n", len(sctx.Hazards))) + b.WriteString(fmt.Sprintf("- Klassifizierungen: %d\n", len(sctx.Classifications))) + b.WriteString(fmt.Sprintf("- Nachweise: %d\n", len(sctx.Evidence))) + b.WriteString("\n") + } + + b.WriteString("---\n") + b.WriteString("*Dieser Abschnitt wurde ohne LLM-Unterstuetzung erstellt und enthaelt nur eine Datenuebersicht. Bitte erneut generieren, wenn der LLM-Service verfuegbar ist.*\n") + + return b.String() +} + +func writeFallbackMitigationList(b *strings.Builder, title string, measures []Mitigation) { + if len(measures) == 0 { + return + } + b.WriteString(fmt.Sprintf("### %s\n\n", title)) + for _, m := range measures { + b.WriteString(fmt.Sprintf("- %s [%s]\n", m.Name, string(m.Status))) + } + b.WriteString("\n") +} + +// ============================================================================ +// Utility helpers +// ============================================================================ + +func countRiskLevels(sctx *SectionGenerationContext) map[string]int { + counts := make(map[string]int) + for _, h := range sctx.Hazards { + if assessments, ok := sctx.Assessments[h.ID]; ok && len(assessments) > 0 { + latest := assessments[len(assessments)-1] + counts[string(latest.RiskLevel)]++ + } + } + return counts +} + +func acceptableLabel(isAcceptable bool) string { + if isAcceptable { + return "[AKZEPTABEL]" + } + return "[NICHT AKZEPTABEL]" +} + +func truncateForPrompt(text string, maxLen int) string { + if len(text) <= maxLen { + return text + } + return text[:maxLen] + "..." +} diff --git a/ai-compliance-sdk/internal/iace/tech_file_generator_prompt_builder.go b/ai-compliance-sdk/internal/iace/tech_file_generator_prompt_builder.go new file mode 100644 index 0000000..fb1e657 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/tech_file_generator_prompt_builder.go @@ -0,0 +1,252 @@ +package iace + +import ( + "fmt" + "strings" +) + +// ============================================================================ +// Prompt builders +// ============================================================================ + +func buildUserPrompt(sctx *SectionGenerationContext, sectionType string) string { + var b strings.Builder + + if sctx == nil || sctx.Project == nil { + b.WriteString("## Maschine / System\n\n- Keine Projektdaten vorhanden.\n\n") + return b.String() + } + + // Machine info — always included + b.WriteString("## Maschine / System\n\n") + b.WriteString(fmt.Sprintf("- **Name:** %s\n", sctx.Project.MachineName)) + b.WriteString(fmt.Sprintf("- **Typ:** %s\n", sctx.Project.MachineType)) + b.WriteString(fmt.Sprintf("- **Hersteller:** %s\n", sctx.Project.Manufacturer)) + if sctx.Project.Description != "" { + b.WriteString(fmt.Sprintf("- **Beschreibung:** %s\n", sctx.Project.Description)) + } + if sctx.Project.CEMarkingTarget != "" { + b.WriteString(fmt.Sprintf("- **CE-Kennzeichnungsziel:** %s\n", sctx.Project.CEMarkingTarget)) + } + if sctx.Project.NarrativeText != "" { + b.WriteString(fmt.Sprintf("\n**Projektbeschreibung:** %s\n", truncateForPrompt(sctx.Project.NarrativeText, 500))) + } + b.WriteString("\n") + + // Components — for most section types + if len(sctx.Components) > 0 && needsComponents(sectionType) { + b.WriteString("## Komponenten\n\n") + for i, c := range sctx.Components { + if i >= 20 { + b.WriteString(fmt.Sprintf("... und %d weitere Komponenten\n", len(sctx.Components)-20)) + break + } + safety := "" + if c.IsSafetyRelevant { + safety = " [SICHERHEITSRELEVANT]" + } + networked := "" + if c.IsNetworked { + networked = " [VERNETZT]" + } + b.WriteString(fmt.Sprintf("- %s (Typ: %s)%s%s", c.Name, string(c.ComponentType), safety, networked)) + if c.Description != "" { + b.WriteString(fmt.Sprintf(" — %s", truncateForPrompt(c.Description, 100))) + } + b.WriteString("\n") + } + b.WriteString("\n") + } + + // Hazards + assessments — for risk-related sections + if len(sctx.Hazards) > 0 && needsHazards(sectionType) { + b.WriteString("## Gefaehrdungen und Risikobewertungen\n\n") + for i, h := range sctx.Hazards { + if i >= 30 { + b.WriteString(fmt.Sprintf("... und %d weitere Gefaehrdungen\n", len(sctx.Hazards)-30)) + break + } + b.WriteString(fmt.Sprintf("### %s\n", h.Name)) + b.WriteString(fmt.Sprintf("- Kategorie: %s", h.Category)) + if h.SubCategory != "" { + b.WriteString(fmt.Sprintf(" / %s", h.SubCategory)) + } + b.WriteString("\n") + if h.LifecyclePhase != "" { + b.WriteString(fmt.Sprintf("- Lebenszyklusphase: %s\n", h.LifecyclePhase)) + } + if h.Scenario != "" { + b.WriteString(fmt.Sprintf("- Szenario: %s\n", truncateForPrompt(h.Scenario, 150))) + } + if h.PossibleHarm != "" { + b.WriteString(fmt.Sprintf("- Moeglicher Schaden: %s\n", h.PossibleHarm)) + } + if h.AffectedPerson != "" { + b.WriteString(fmt.Sprintf("- Betroffene Person: %s\n", h.AffectedPerson)) + } + b.WriteString(fmt.Sprintf("- Status: %s\n", string(h.Status))) + + // Latest assessment + if assessments, ok := sctx.Assessments[h.ID]; ok && len(assessments) > 0 { + a := assessments[len(assessments)-1] // latest + b.WriteString(fmt.Sprintf("- Bewertung: S=%d E=%d P=%d → Risiko=%.1f (%s) %s\n", + a.Severity, a.Exposure, a.Probability, + a.ResidualRisk, string(a.RiskLevel), + acceptableLabel(a.IsAcceptable))) + } + b.WriteString("\n") + } + } + + // Mitigations — for mitigation/verification sections + if needsMitigations(sectionType) { + designMeasures, protectiveMeasures, infoMeasures := groupMitigations(sctx) + if len(designMeasures)+len(protectiveMeasures)+len(infoMeasures) > 0 { + b.WriteString("## Risikomindernde Massnahmen (3-Stufen-Methode)\n\n") + writeMitigationGroup(&b, "Stufe 1: Inhaerent sichere Konstruktion (Design)", designMeasures) + writeMitigationGroup(&b, "Stufe 2: Technische Schutzmassnahmen (Protective)", protectiveMeasures) + writeMitigationGroup(&b, "Stufe 3: Benutzerinformation (Information)", infoMeasures) + } + } + + // Classifications — for classification/standards sections + if len(sctx.Classifications) > 0 && needsClassifications(sectionType) { + b.WriteString("## Regulatorische Klassifizierungen\n\n") + for _, c := range sctx.Classifications { + b.WriteString(fmt.Sprintf("- **%s:** %s (Risiko: %s)\n", + string(c.Regulation), c.ClassificationResult, string(c.RiskLevel))) + if c.Reasoning != "" { + b.WriteString(fmt.Sprintf(" Begruendung: %s\n", truncateForPrompt(c.Reasoning, 200))) + } + } + b.WriteString("\n") + } + + // Evidence — for evidence/verification sections + if len(sctx.Evidence) > 0 && needsEvidence(sectionType) { + b.WriteString("## Vorhandene Nachweise\n\n") + for i, e := range sctx.Evidence { + if i >= 30 { + b.WriteString(fmt.Sprintf("... und %d weitere Nachweise\n", len(sctx.Evidence)-30)) + break + } + b.WriteString(fmt.Sprintf("- %s", e.FileName)) + if e.Description != "" { + b.WriteString(fmt.Sprintf(" — %s", truncateForPrompt(e.Description, 100))) + } + b.WriteString("\n") + } + b.WriteString("\n") + } + + // RAG context — if available + if sctx.RAGContext != "" { + b.WriteString("## Relevante Rechtsgrundlagen (RAG)\n\n") + b.WriteString(sctx.RAGContext) + b.WriteString("\n\n") + } + + // Instruction + b.WriteString("---\n\n") + b.WriteString("Erstelle den Abschnitt basierend auf den obigen Daten. Schreibe auf Deutsch, verwende Markdown-Formatierung und beziehe dich auf die konkreten Projektdaten.\n") + + return b.String() +} + +// ============================================================================ +// Section type → data requirements +// ============================================================================ + +func needsComponents(sectionType string) bool { + switch sectionType { + case SectionGeneralDescription, SectionDesignSpecifications, SectionComponentList, + SectionEssentialRequirements, SectionAIModelDescription, SectionAIIntendedPurpose, + SectionClassificationReport, SectionInstructionsForUse: + return true + } + return false +} + +func needsHazards(sectionType string) bool { + switch sectionType { + case SectionRiskAssessmentReport, SectionHazardLogCombined, SectionEssentialRequirements, + SectionMitigationReport, SectionVerificationReport, SectionTestReports, + SectionAIRiskManagement, SectionInstructionsForUse, SectionMonitoringPlan: + return true + } + return false +} + +func needsMitigations(sectionType string) bool { + switch sectionType { + case SectionRiskAssessmentReport, SectionMitigationReport, SectionVerificationReport, + SectionTestReports, SectionEssentialRequirements, SectionAIRiskManagement, + SectionAIHumanOversight, SectionInstructionsForUse: + return true + } + return false +} + +func needsClassifications(sectionType string) bool { + switch sectionType { + case SectionClassificationReport, SectionEssentialRequirements, SectionStandardsApplied, + SectionDeclarationConformity, SectionAIIntendedPurpose, SectionAIRiskManagement, + SectionGeneralDescription: + return true + } + return false +} + +func needsEvidence(sectionType string) bool { + switch sectionType { + case SectionEvidenceIndex, SectionVerificationReport, SectionTestReports, + SectionMitigationReport: + return true + } + return false +} + +// ============================================================================ +// Mitigation grouping helpers +// ============================================================================ + +func groupMitigations(sctx *SectionGenerationContext) (design, protective, info []Mitigation) { + for _, mits := range sctx.Mitigations { + for _, m := range mits { + switch m.ReductionType { + case ReductionTypeDesign: + design = append(design, m) + case ReductionTypeProtective: + protective = append(protective, m) + case ReductionTypeInformation: + info = append(info, m) + } + } + } + return +} + +func writeMitigationGroup(b *strings.Builder, title string, measures []Mitigation) { + if len(measures) == 0 { + return + } + b.WriteString(fmt.Sprintf("### %s\n\n", title)) + for i, m := range measures { + if i >= 20 { + b.WriteString(fmt.Sprintf("... und %d weitere Massnahmen\n", len(measures)-20)) + break + } + b.WriteString(fmt.Sprintf("- **%s** [%s]", m.Name, string(m.Status))) + if m.VerificationMethod != "" { + b.WriteString(fmt.Sprintf(" — Verifikation: %s", string(m.VerificationMethod))) + if m.VerificationResult != "" { + b.WriteString(fmt.Sprintf(" (%s)", m.VerificationResult)) + } + } + b.WriteString("\n") + if m.Description != "" { + b.WriteString(fmt.Sprintf(" %s\n", truncateForPrompt(m.Description, 150))) + } + } + b.WriteString("\n") +} diff --git a/ai-compliance-sdk/internal/iace/tech_file_generator_prompts.go b/ai-compliance-sdk/internal/iace/tech_file_generator_prompts.go new file mode 100644 index 0000000..2722ced --- /dev/null +++ b/ai-compliance-sdk/internal/iace/tech_file_generator_prompts.go @@ -0,0 +1,141 @@ +package iace + +// ============================================================================ +// Section type constants +// ============================================================================ + +const ( + SectionRiskAssessmentReport = "risk_assessment_report" + SectionHazardLogCombined = "hazard_log_combined" + SectionGeneralDescription = "general_description" + SectionEssentialRequirements = "essential_requirements" + SectionDesignSpecifications = "design_specifications" + SectionTestReports = "test_reports" + SectionStandardsApplied = "standards_applied" + SectionDeclarationConformity = "declaration_of_conformity" + SectionAIIntendedPurpose = "ai_intended_purpose" + SectionAIModelDescription = "ai_model_description" + SectionAIRiskManagement = "ai_risk_management" + SectionAIHumanOversight = "ai_human_oversight" + SectionComponentList = "component_list" + SectionClassificationReport = "classification_report" + SectionMitigationReport = "mitigation_report" + SectionVerificationReport = "verification_report" + SectionEvidenceIndex = "evidence_index" + SectionInstructionsForUse = "instructions_for_use" + SectionMonitoringPlan = "monitoring_plan" +) + +// ============================================================================ +// System prompts (German — CE compliance context) +// ============================================================================ + +var sectionSystemPrompts = map[string]string{ + SectionRiskAssessmentReport: `Du bist CE-Experte fuer Maschinen- und KI-Sicherheit. Erstelle eine strukturierte Zusammenfassung der Risikobeurteilung gemaess ISO 12100 und EN ISO 13849. Gliederung: 1) Methodik, 2) Risikoueberblick (Anzahl Gefaehrdungen nach Risikostufe), 3) Kritische Risiken, 4) Akzeptanzbewertung, 5) Empfehlungen. Verwende Fachterminologie und beziehe dich auf die konkreten Projektdaten.`, + + SectionHazardLogCombined: `Erstelle ein tabellarisches Gefaehrdungsprotokoll (Hazard Log) fuer die technische Dokumentation. Jede Gefaehrdung soll enthalten: ID, Bezeichnung, Kategorie, Lebenszyklusphase, Szenario, Schwere, Eintrittswahrscheinlichkeit, Risikolevel, Massnahmen und Status. Formatiere als strukturierte Tabelle in Markdown.`, + + SectionGeneralDescription: `Erstelle eine allgemeine Maschinenbeschreibung fuer die technische Dokumentation gemaess EU-Maschinenverordnung 2023/1230 Anhang IV. Beschreibe: 1) Bestimmungsgemaesse Verwendung, 2) Aufbau und Funktion, 3) Systemkomponenten, 4) Betriebsbedingungen, 5) Schnittstellen. Verwende die bereitgestellten Projektdaten.`, + + SectionEssentialRequirements: `Beschreibe die anwendbaren grundlegenden Anforderungen (Essential Health and Safety Requirements — EHSR) gemaess EU-Maschinenverordnung 2023/1230 Anhang III. Ordne jede Anforderung den relevanten Gefaehrdungen und Massnahmen zu. Beruecksichtige auch AI Act und CRA Anforderungen falls KI-Komponenten vorhanden sind.`, + + SectionDesignSpecifications: `Erstelle eine Uebersicht der Konstruktionsdaten und Spezifikationen fuer die technische Dokumentation. Enthalten sein sollen: 1) Systemarchitektur, 2) Komponentenliste mit Sicherheitsrelevanz, 3) Software-/Firmware-Versionen, 4) Schnittstellenbeschreibungen, 5) Sicherheitsfunktionen. Beziehe dich auf die konkreten Komponenten.`, + + SectionTestReports: `Erstelle eine Zusammenfassung der Pruefberichte und Verifikationsergebnisse. Gliederung: 1) Durchgefuehrte Pruefungen, 2) Pruefmethoden (Test, Analyse, Inspektion), 3) Ergebnisse pro Massnahme, 4) Offene Punkte, 5) Gesamtbewertung. Referenziere die konkreten Mitigationsmassnahmen und deren Verifikationsstatus.`, + + SectionStandardsApplied: `Liste die angewandten harmonisierten Normen und technischen Spezifikationen auf. Ordne jede Norm den relevanten Anforderungen und Gefaehrdungskategorien zu. Beruecksichtige: ISO 12100, ISO 13849, IEC 62443, ISO/IEC 27001, sowie branchenspezifische Normen. Erklaere die Vermutungswirkung (Presumption of Conformity).`, + + SectionDeclarationConformity: `Erstelle eine EU-Konformitaetserklaerung nach EU-Maschinenverordnung 2023/1230 Anhang IV. Enthalten sein muessen: 1) Hersteller-Angaben, 2) Produktidentifikation, 3) Angewandte Richtlinien und Verordnungen, 4) Angewandte Normen, 5) Bevollmaechtigter, 6) Ort, Datum, Unterschrift. Formales Dokument-Layout.`, + + SectionAIIntendedPurpose: `Beschreibe den bestimmungsgemaessen Zweck des KI-Systems gemaess AI Act Art. 13 (Transparenzpflichten). Enthalten sein sollen: 1) Zweckbestimmung, 2) Einsatzbereich und -grenzen, 3) Zielgruppe, 4) Vorhersehbarer Fehlgebrauch, 5) Leistungskennzahlen, 6) Einschraenkungen und bekannte Risiken.`, + + SectionAIModelDescription: `Beschreibe das KI-Modell, die Trainingsdaten und die Architektur gemaess AI Act Anhang IV. Enthalten: 1) Modelltyp und Architektur, 2) Trainingsdaten (Herkunft, Umfang, Qualitaet), 3) Validierungsmethodik, 4) Leistungsmetriken, 5) Bekannte Verzerrungen (Bias), 6) Energie-/Ressourcenverbrauch.`, + + SectionAIRiskManagement: `Erstelle eine Beschreibung des KI-Risikomanagementsystems gemaess AI Act Art. 9. Gliederung: 1) Risikomanagement-Prozess, 2) Identifizierte Risiken fuer Gesundheit/Sicherheit/Grundrechte, 3) Risikomindernde Massnahmen, 4) Restrisiken, 5) Ueberwachungs- und Aktualisierungsverfahren.`, + + SectionAIHumanOversight: `Beschreibe die Massnahmen zur menschlichen Aufsicht (Human Oversight) gemaess AI Act Art. 14. Enthalten: 1) Aufsichtskonzept, 2) Rollen und Verantwortlichkeiten, 3) Eingriffsmoglichkeiten, 4) Uebersteuern/Abschalten, 5) Schulungsanforderungen, 6) Informationspflichten an Nutzer.`, + + SectionComponentList: `Erstelle eine detaillierte Komponentenliste fuer die technische Dokumentation. Pro Komponente: Name, Typ, Version, Beschreibung, Sicherheitsrelevanz, Vernetzungsstatus. Kennzeichne sicherheitsrelevante und vernetzte Komponenten besonders. Gruppiere nach Komponententyp.`, + + SectionClassificationReport: `Erstelle einen Klassifizierungsbericht, der die regulatorische Einordnung des Produkts zusammenfasst. Pro Verordnung (MVO, AI Act, CRA, NIS2): Klassifizierungsergebnis, Risikoklasse, Begruendung, daraus resultierende Anforderungen. Bewerte die Gesamtkonformitaetslage.`, + + SectionMitigationReport: `Erstelle einen Massnahmenbericht (Mitigation Report) fuer die technische Dokumentation. Gliederung nach 3-Stufen-Methode: 1) Inhaerent sichere Konstruktion (Design), 2) Technische Schutzmassnahmen (Protective), 3) Benutzerinformation (Information). Pro Massnahme: Status, Verifikation, zugeordnete Gefaehrdung.`, + + SectionVerificationReport: `Erstelle einen Verifikationsbericht ueber alle durchgefuehrten Pruef- und Nachweisverfahren. Enthalten: 1) Verifikationsplan-Uebersicht, 2) Durchgefuehrte Pruefungen nach Methode, 3) Ergebnisse und Bewertung, 4) Offene Verifikationen, 5) Gesamtstatus der Konformitaetsnachweise.`, + + SectionEvidenceIndex: `Erstelle ein Nachweisverzeichnis (Evidence Index) fuer die technische Dokumentation. Liste alle vorhandenen Nachweisdokumente auf: Dateiname, Beschreibung, zugeordnete Massnahme, Dokumenttyp. Identifiziere fehlende Nachweise und empfehle Ergaenzungen.`, + + SectionInstructionsForUse: `Erstelle eine Gliederung fuer die Betriebsanleitung gemaess EU-Maschinenverordnung 2023/1230 Anhang III Abschnitt 1.7.4. Enthalten: 1) Bestimmungsgemaesse Verwendung, 2) Inbetriebnahme, 3) Sicherer Betrieb, 4) Wartung, 5) Restrisiken und Warnhinweise, 6) Ausserbetriebnahme. Beruecksichtige identifizierte Gefaehrdungen.`, + + SectionMonitoringPlan: `Erstelle einen Post-Market-Monitoring-Plan fuer das Produkt. Enthalten: 1) Ueberwachungsziele, 2) Datenquellen (Kundenfeedback, Vorfaelle, Updates), 3) Ueberwachungsintervalle, 4) Eskalationsverfahren, 5) Dokumentationspflichten, 6) Verantwortlichkeiten. Beruecksichtige AI Act Art. 72 (Post-Market Monitoring) falls KI-Komponenten vorhanden.`, +} + +// ============================================================================ +// RAG query mapping +// ============================================================================ + +func buildRAGQuery(sectionType string) string { + ragQueries := map[string]string{ + SectionRiskAssessmentReport: "Risikobeurteilung ISO 12100 Risikobewertung Maschine Gefaehrdungsanalyse", + SectionHazardLogCombined: "Gefaehrdungsprotokoll Hazard Log Risikoanalyse Gefaehrdungsidentifikation", + SectionGeneralDescription: "Maschinenbeschreibung technische Dokumentation bestimmungsgemaesse Verwendung", + SectionEssentialRequirements: "grundlegende Anforderungen EHSR Maschinenverordnung Anhang III Sicherheitsanforderungen", + SectionDesignSpecifications: "Konstruktionsdaten Spezifikationen Systemarchitektur technische Dokumentation", + SectionTestReports: "Pruefberichte Verifikation Validierung Konformitaetsbewertung Testberichte", + SectionStandardsApplied: "harmonisierte Normen ISO 12100 ISO 13849 IEC 62443 Vermutungswirkung", + SectionDeclarationConformity: "EU-Konformitaetserklaerung Maschinenverordnung 2023/1230 Anhang IV CE-Kennzeichnung", + SectionAIIntendedPurpose: "bestimmungsgemaesser Zweck KI-System AI Act Art. 13 Transparenz Intended Purpose", + SectionAIModelDescription: "KI-Modell Trainingsdaten Architektur AI Act Anhang IV technische Dokumentation", + SectionAIRiskManagement: "KI-Risikomanagementsystem AI Act Art. 9 Risikomanagement kuenstliche Intelligenz", + SectionAIHumanOversight: "menschliche Aufsicht Human Oversight AI Act Art. 14 Kontrolle KI-System", + SectionComponentList: "Komponentenliste Systemkomponenten sicherheitsrelevante Bauteile technische Dokumentation", + SectionClassificationReport: "regulatorische Klassifizierung Risikoklasse AI Act CRA Maschinenverordnung", + SectionMitigationReport: "Risikomindernde Massnahmen 3-Stufen-Methode ISO 12100 Schutzmassnahmen", + SectionVerificationReport: "Verifikation Validierung Pruefnachweis Konformitaetsbewertung Pruefprotokoll", + SectionEvidenceIndex: "Nachweisdokumente Evidence Konformitaetsnachweis Dokumentenindex", + SectionInstructionsForUse: "Betriebsanleitung Benutzerinformation Maschinenverordnung Abschnitt 1.7.4 Sicherheitshinweise", + SectionMonitoringPlan: "Post-Market-Monitoring Ueberwachungsplan AI Act Art. 72 Marktbeobachtung", + } + + if q, ok := ragQueries[sectionType]; ok { + return q + } + return "CE-Konformitaet technische Dokumentation Maschinenverordnung AI Act" +} + +// getSystemPrompt returns the system prompt for a given section type. +func getSystemPrompt(sectionType string) string { + if prompt, ok := sectionSystemPrompts[sectionType]; ok { + return prompt + } + return "Du bist CE-Experte fuer technische Dokumentation. Erstelle den angeforderten Abschnitt der technischen Dokumentation basierend auf den bereitgestellten Projektdaten. Schreibe auf Deutsch, verwende Fachterminologie und beziehe dich auf die konkreten Daten." +} + +// sectionDisplayName returns a human-readable name for a section type. +func sectionDisplayName(sectionType string) string { + names := map[string]string{ + SectionRiskAssessmentReport: "Zusammenfassung der Risikobeurteilung", + SectionHazardLogCombined: "Gefaehrdungsprotokoll (Hazard Log)", + SectionGeneralDescription: "Allgemeine Maschinenbeschreibung", + SectionEssentialRequirements: "Grundlegende Anforderungen (EHSR)", + SectionDesignSpecifications: "Konstruktionsdaten und Spezifikationen", + SectionTestReports: "Pruefberichte", + SectionStandardsApplied: "Angewandte Normen", + SectionDeclarationConformity: "EU-Konformitaetserklaerung", + SectionAIIntendedPurpose: "Bestimmungsgemaesser Zweck (KI)", + SectionAIModelDescription: "KI-Modellbeschreibung", + SectionAIRiskManagement: "KI-Risikomanagementsystem", + SectionAIHumanOversight: "Menschliche Aufsicht (Human Oversight)", + SectionComponentList: "Komponentenliste", + SectionClassificationReport: "Klassifizierungsbericht", + SectionMitigationReport: "Massnahmenbericht", + SectionVerificationReport: "Verifikationsbericht", + SectionEvidenceIndex: "Nachweisverzeichnis", + SectionInstructionsForUse: "Betriebsanleitung (Gliederung)", + SectionMonitoringPlan: "Post-Market-Monitoring-Plan", + } + if name, ok := names[sectionType]; ok { + return name + } + return sectionType +}