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:
@@ -44,310 +44,6 @@ type CompletenessResult struct {
|
|||||||
CanExport bool `json:"can_export"`
|
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
|
// CompletenessChecker
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
305
ai-compliance-sdk/internal/iace/completeness_gates.go
Normal file
305
ai-compliance-sdk/internal/iace/completeness_gates.go
Normal 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
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,13 @@ package iace
|
|||||||
// GetExtendedHazardPatterns returns 58 additional patterns
|
// GetExtendedHazardPatterns returns 58 additional patterns
|
||||||
// derived from the Rule Library documents (R051-R1550).
|
// derived from the Rule Library documents (R051-R1550).
|
||||||
// These supplement the 44 built-in patterns in hazard_patterns.go.
|
// 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 {
|
func GetExtendedHazardPatterns() []HazardPattern {
|
||||||
|
return append(getExtendedHazardPatternsA(), getExtendedHazardPatternsB()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getExtendedHazardPatternsA returns patterns HP045-HP073.
|
||||||
|
func getExtendedHazardPatternsA() []HazardPattern {
|
||||||
return []HazardPattern{
|
return []HazardPattern{
|
||||||
{
|
{
|
||||||
ID: "HP045", NameDE: "Aktor — elektrisch", NameEN: "Actuator — electrical",
|
ID: "HP045", NameDE: "Aktor — elektrisch", NameEN: "Actuator — electrical",
|
||||||
@@ -324,324 +330,5 @@ func GetExtendedHazardPatterns() []HazardPattern {
|
|||||||
Priority: 70,
|
Priority: 70,
|
||||||
// Source: R574, R1074
|
// 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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
327
ai-compliance-sdk/internal/iace/hazard_patterns_extended2.go
Normal file
327
ai-compliance-sdk/internal/iace/hazard_patterns_extended2.go
Normal 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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
package iace
|
package iace
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Constants / Enums
|
// Constants / Enums
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -139,11 +132,11 @@ const (
|
|||||||
type MonitoringEventType string
|
type MonitoringEventType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MonitoringEventTypeIncident MonitoringEventType = "incident"
|
MonitoringEventTypeIncident MonitoringEventType = "incident"
|
||||||
MonitoringEventTypeUpdate MonitoringEventType = "update"
|
MonitoringEventTypeUpdate MonitoringEventType = "update"
|
||||||
MonitoringEventTypeDriftAlert MonitoringEventType = "drift_alert"
|
MonitoringEventTypeDriftAlert MonitoringEventType = "drift_alert"
|
||||||
MonitoringEventTypeRegulationChange MonitoringEventType = "regulation_change"
|
MonitoringEventTypeRegulationChange MonitoringEventType = "regulation_change"
|
||||||
MonitoringEventTypeAudit MonitoringEventType = "audit"
|
MonitoringEventTypeAudit MonitoringEventType = "audit"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuditAction represents the type of action recorded in the audit trail
|
// AuditAction represents the type of action recorded in the audit trail
|
||||||
@@ -198,427 +191,3 @@ const (
|
|||||||
ReviewStatusApproved ReviewStatus = "approved"
|
ReviewStatusApproved ReviewStatus = "approved"
|
||||||
ReviewStatusRejected ReviewStatus = "rejected"
|
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"`
|
|
||||||
}
|
|
||||||
|
|||||||
203
ai-compliance-sdk/internal/iace/models_api.go
Normal file
203
ai-compliance-sdk/internal/iace/models_api.go
Normal 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"`
|
||||||
|
}
|
||||||
236
ai-compliance-sdk/internal/iace/models_entities.go
Normal file
236
ai-compliance-sdk/internal/iace/models_entities.go
Normal 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"`
|
||||||
|
}
|
||||||
@@ -42,109 +42,6 @@ type SectionGenerationContext struct {
|
|||||||
RAGContext string // aggregated text from RAG search
|
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
|
// BuildSectionContext — loads all project data + RAG context
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -225,7 +122,7 @@ func (g *TechFileGenerator) BuildSectionContext(ctx context.Context, projectID u
|
|||||||
Mitigations: mitigations,
|
Mitigations: mitigations,
|
||||||
Classifications: classifications,
|
Classifications: classifications,
|
||||||
Evidence: evidence,
|
Evidence: evidence,
|
||||||
RAGContext: ragContext,
|
RAGContext: ragContext,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,419 +158,3 @@ func (g *TechFileGenerator) GenerateSection(ctx context.Context, projectID uuid.
|
|||||||
|
|
||||||
return resp.Message.Content, nil
|
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] + "..."
|
|
||||||
}
|
|
||||||
|
|||||||
141
ai-compliance-sdk/internal/iace/tech_file_generator_fallback.go
Normal file
141
ai-compliance-sdk/internal/iace/tech_file_generator_fallback.go
Normal 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] + "..."
|
||||||
|
}
|
||||||
@@ -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")
|
||||||
|
}
|
||||||
141
ai-compliance-sdk/internal/iace/tech_file_generator_prompts.go
Normal file
141
ai-compliance-sdk/internal/iace/tech_file_generator_prompts.go
Normal 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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user