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