refactor(go/iace): split tech_file_generator, hazard_patterns, models, completeness

Split 4 oversized files (503-679 LOC each) into focused units all under 500 LOC:
- tech_file_generator.go → +_prompts, +_prompt_builder, +_fallback
- hazard_patterns_extended.go → +_extended2.go (HP074-HP102 extracted)
- models.go → +_entities.go, +_api.go (enums / DB entities / API types)
- completeness.go → +_gates.go (gate definitions extracted)

All files remain in package iace. Zero behavior changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-19 10:03:44 +02:00
parent 13f57c4519
commit 3f1444541f
11 changed files with 1616 additions and 1578 deletions

View File

@@ -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
// ============================================================================

View File

@@ -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
},
},
}
}

View File

@@ -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
},
}
}

View File

@@ -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
},
}
}

View File

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

View File

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

View File

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

View File

@@ -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] + "..."
}

View File

@@ -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] + "..."
}

View File

@@ -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")
}

View File

@@ -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
}