diff --git a/ai-compliance-sdk/internal/api/handlers/iace_handler_refdata.go b/ai-compliance-sdk/internal/api/handlers/iace_handler_refdata.go index 4cf6a2d..51a50ab 100644 --- a/ai-compliance-sdk/internal/api/handlers/iace_handler_refdata.go +++ b/ai-compliance-sdk/internal/api/handlers/iace_handler_refdata.go @@ -86,6 +86,31 @@ func (h *IACEHandler) ListProtectiveMeasures(c *gin.Context) { }) } +// ListFailureModes handles GET /failure-modes +// Returns the failure mode library, optionally filtered by ?component_type. +func (h *IACEHandler) ListFailureModes(c *gin.Context) { + componentType := c.Query("component_type") + + all := iace.GetFailureModeLibrary() + + var filtered []iace.FailureModeEntry + for _, entry := range all { + if componentType != "" && entry.ComponentType != componentType { + continue + } + filtered = append(filtered, entry) + } + + if filtered == nil { + filtered = []iace.FailureModeEntry{} + } + + c.JSON(http.StatusOK, gin.H{ + "failure_modes": filtered, + "total": len(filtered), + }) +} + // ValidateMitigationHierarchy handles POST /projects/:id/validate-mitigation-hierarchy // Validates if the proposed mitigation type follows the 3-step hierarchy principle. func (h *IACEHandler) ValidateMitigationHierarchy(c *gin.Context) { diff --git a/ai-compliance-sdk/internal/app/routes.go b/ai-compliance-sdk/internal/app/routes.go index a658607..7c69641 100644 --- a/ai-compliance-sdk/internal/app/routes.go +++ b/ai-compliance-sdk/internal/app/routes.go @@ -361,6 +361,7 @@ func registerIACERoutes(v1 *gin.RouterGroup, h *handlers.IACEHandler) { iaceRoutes.GET("/roles", h.ListRoles) iaceRoutes.GET("/evidence-types", h.ListEvidenceTypes) iaceRoutes.GET("/protective-measures-library", h.ListProtectiveMeasures) + iaceRoutes.GET("/failure-modes", h.ListFailureModes) iaceRoutes.GET("/component-library", h.ListComponentLibrary) iaceRoutes.GET("/energy-sources", h.ListEnergySources) iaceRoutes.GET("/tags", h.ListTags) diff --git a/ai-compliance-sdk/internal/iace/failure_mode_library.go b/ai-compliance-sdk/internal/iace/failure_mode_library.go new file mode 100644 index 0000000..2012201 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/failure_mode_library.go @@ -0,0 +1,122 @@ +package iace + +// GetFailureModeLibrary returns the complete failure mode library. +func GetFailureModeLibrary() []FailureModeEntry { + var all []FailureModeEntry + all = append(all, getSensorFailureModes()...) + all = append(all, getControllerFailureModes()...) + all = append(all, getActuatorFailureModes()...) + all = append(all, getMechanicalFailureModes()...) + all = append(all, getElectricalFailureModes()...) + all = append(all, getSoftwareFailureModes()...) + all = append(all, getFluidFailureModes()...) + all = append(all, getSafetyDeviceFailureModes()...) + all = append(all, getNetworkFailureModes()...) + all = append(all, getAIFailureModes()...) + return all +} + +// ── Sensor Failure Modes (20) ────────────────────────────────────── +func getSensorFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-SEN-01", ComponentType: "sensor", Mode: "loss_of_signal", NameDE: "Signalverlust", NameEN: "Loss of signal", Effect: "Positionsinformation geht verloren, Steuerung erhaelt keine Rueckmeldung", DetectionHint: "Diagnosefunktion Safety-SPS, Drahtbruchueberwachung", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-SEN-02", ComponentType: "sensor", Mode: "drift", NameDE: "Messwertdrift", NameEN: "Measurement drift", Effect: "Langsame Abweichung vom Sollwert, schleichender Genauigkeitsverlust", DetectionHint: "Regelmaessige Kalibrierung, Plausibilitaetspruefung", DefaultSeverity: 6, DefaultOccurrence: 4, DefaultDetection: 5}, + {ID: "FM-SEN-03", ComponentType: "sensor", Mode: "false_positive", NameDE: "Falschmeldung (Fehlalarm)", NameEN: "False positive", Effect: "Unnoetiger Maschinenstopp, Produktionsverlust", DetectionHint: "Statistik der Alarme, Vergleich Redundanzsensor", DefaultSeverity: 3, DefaultOccurrence: 4, DefaultDetection: 3}, + {ID: "FM-SEN-04", ComponentType: "sensor", Mode: "false_negative", NameDE: "Nichtmeldung (Fehlersuppression)", NameEN: "False negative", Effect: "Gefaehrlicher Zustand wird nicht erkannt, Schutzfunktion versagt", DetectionHint: "Zyklischer Selbsttest, diversitaerer Sensor", DefaultSeverity: 10, DefaultOccurrence: 2, DefaultDetection: 7}, + {ID: "FM-SEN-05", ComponentType: "sensor", Mode: "calibration_error", NameDE: "Kalibrierungsfehler", NameEN: "Calibration error", Effect: "Systematische Messabweichung, falsche Grenzwertbewertung", DetectionHint: "Referenzmessung mit Prueflehre", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 5}, + {ID: "FM-SEN-06", ComponentType: "sensor", Mode: "environmental_interference", NameDE: "Umgebungseinfluss-Stoerung", NameEN: "Environmental interference", Effect: "EMV, Temperatur oder Verschmutzung verfaelscht Messwert", DetectionHint: "Abschirmung pruefen, Plausibilitaetscheck", DefaultSeverity: 6, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-SEN-07", ComponentType: "sensor", Mode: "response_time_degradation", NameDE: "Reaktionszeit-Verschlechterung", NameEN: "Response time degradation", Effect: "Sicherheitsfunktion reagiert zu langsam auf Gefahrensituation", DetectionHint: "Periodische Reaktionszeitmessung", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 6}, + {ID: "FM-SEN-08", ComponentType: "sensor", Mode: "stuck_at_value", NameDE: "Festhaengen auf Wert", NameEN: "Stuck at value", Effect: "Sensor liefert unveraenderlichen Wert, Zustandsaenderung wird nicht erkannt", DetectionHint: "Aenderungsrate-Ueberwachung, Watchdog", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-SEN-09", ComponentType: "sensor", Mode: "intermittent_contact", NameDE: "Wackelkontakt", NameEN: "Intermittent contact", Effect: "Sporadischer Signalausfall, schwer reproduzierbar", DetectionHint: "Vibrations-Test, Steckerpruefung", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 7}, + {ID: "FM-SEN-10", ComponentType: "sensor", Mode: "cross_talk", NameDE: "Signaleinstreuung (Crosstalk)", NameEN: "Signal crosstalk", Effect: "Fremdsignal ueberlagert Messwert, Fehlinterpretation", DetectionHint: "EMV-Test, geschirmte Leitungen pruefen", DefaultSeverity: 6, DefaultOccurrence: 3, DefaultDetection: 5}, + {ID: "FM-SEN-11", ComponentType: "sensor", Mode: "power_supply_failure", NameDE: "Versorgungsspannungsausfall Sensor", NameEN: "Sensor power supply failure", Effect: "Sensor liefert kein Signal, Steuerung ohne Rueckmeldung", DetectionHint: "Spannungsueberwachung, Redundante Versorgung", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-SEN-12", ComponentType: "sensor", Mode: "mechanical_damage", NameDE: "Mechanische Beschaedigung Sensor", NameEN: "Sensor mechanical damage", Effect: "Sensor physisch zerstoert oder dejustiert durch Kollision/Vibration", DetectionHint: "Sichtpruefung, Montagekontrolle", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-SEN-13", ComponentType: "sensor", Mode: "aging", NameDE: "Alterung/Verschleiss Sensor", NameEN: "Sensor aging", Effect: "Empfindlichkeit nimmt ab, Schaltpunkte verschieben sich", DetectionHint: "Lebensdauer-Tracking, praeventiver Austausch", DefaultSeverity: 5, DefaultOccurrence: 4, DefaultDetection: 5}, + {ID: "FM-SEN-14", ComponentType: "sensor", Mode: "contamination", NameDE: "Verschmutzung Sensorflaeche", NameEN: "Sensor contamination", Effect: "Optischer/induktiver Sensor durch Oel, Staub oder Spaene beeintraechtigt", DetectionHint: "Reinigungsplan, Signalstaerke-Ueberwachung", DefaultSeverity: 5, DefaultOccurrence: 5, DefaultDetection: 3}, + {ID: "FM-SEN-15", ComponentType: "sensor", Mode: "wrong_installation", NameDE: "Falsche Montage/Ausrichtung", NameEN: "Wrong installation", Effect: "Sensor misst an falscher Stelle oder in falscher Richtung", DetectionHint: "Inbetriebnahme-Checkliste, Referenzmessung", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 3}, + + // Encoder-specific + {ID: "FM-SEN-16", ComponentType: "sensor", Mode: "encoder_pulse_loss", NameDE: "Encoder-Impulsverlust", NameEN: "Encoder pulse loss", Effect: "Positionszaehler weicht ab, Achse verfaehrt unkontrolliert", DetectionHint: "Inkremental-Encoder Referenzmarke pruefen", DefaultSeverity: 9, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-SEN-17", ComponentType: "sensor", Mode: "encoder_cable_break", NameDE: "Encoder-Kabelbruch", NameEN: "Encoder cable break", Effect: "Kompletter Positionsverlust, STO wird ausgeloest", DetectionHint: "Drahtbrucherkennung im Safety-Encoder", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 2}, + + // Safety-specific sensors + {ID: "FM-SEN-18", ComponentType: "sensor", Mode: "safety_switch_bypass", NameDE: "Sicherheitsschalter ueberbrueckt", NameEN: "Safety switch bypassed", Effect: "Schutzeinrichtung wirkungslos, Zugang zum Gefahrbereich moeglich", DetectionHint: "Codierter Schalter, Manipulationsschutz", DefaultSeverity: 10, DefaultOccurrence: 2, DefaultDetection: 6}, + {ID: "FM-SEN-19", ComponentType: "sensor", Mode: "light_curtain_blind_spot", NameDE: "Lichtvorhang Totwinkel", NameEN: "Light curtain blind spot", Effect: "Person im Gefahrbereich wird nicht erkannt", DetectionHint: "Ausrichtungspruefung, Testkoerper-Pruefung", DefaultSeverity: 10, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-SEN-20", ComponentType: "sensor", Mode: "pressure_sensor_blockage", NameDE: "Drucksensor-Verstopfung", NameEN: "Pressure sensor blockage", Effect: "Druckanzeige zeigt falschen Wert, Ueberdruck nicht erkannt", DetectionHint: "Vergleichsmessung, Spuelprozedur", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 5}, + } +} + +// ── Controller Failure Modes (20) ────────────────────────────────── +func getControllerFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-CTRL-01", ComponentType: "controller", Mode: "watchdog_timeout", NameDE: "Watchdog-Timeout", NameEN: "Watchdog timeout", Effect: "SPS-Programm reagiert nicht mehr, sicherer Zustand wird erzwungen", DetectionHint: "Hardware-Watchdog, LED-Anzeige", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-CTRL-02", ComponentType: "controller", Mode: "memory_overflow", NameDE: "Speicherueberlauf", NameEN: "Memory overflow", Effect: "Programmabsturz, undefiniertes Steuerungsverhalten", DetectionHint: "Speicher-Monitoring, Stack-Ueberwachung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-CTRL-03", ComponentType: "controller", Mode: "communication_loss", NameDE: "Busverlust/Kommunikationsausfall", NameEN: "Communication loss", Effect: "Steuerung verliert Verbindung zu Antrieben oder Sensorik", DetectionHint: "Bus-Timeout-Ueberwachung, Heartbeat", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 2}, + {ID: "FM-CTRL-04", ComponentType: "controller", Mode: "program_corruption", NameDE: "Programm-Korruption", NameEN: "Program corruption", Effect: "Steuerungsprogramm laeuft fehlerhaft, unvorhersehbare Ausgaben", DetectionHint: "CRC-Pruefung, ROM-Integritaetstest", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 4}, + {ID: "FM-CTRL-05", ComponentType: "controller", Mode: "parameter_loss", NameDE: "Parameterverlust nach Spannungsausfall", NameEN: "Parameter loss after power failure", Effect: "Maschine startet mit Default-Parametern, falsche Grenzwerte", DetectionHint: "Batterie-Ueberwachung, Backup-Vergleich", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-CTRL-06", ComponentType: "controller", Mode: "output_stuck", NameDE: "Ausgang klebt (stuck-at)", NameEN: "Output stuck", Effect: "Aktor wird nicht mehr angesteuert oder laeuft dauerhaft", DetectionHint: "Ruecklese-Diagnose, Cross-Monitoring", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-CTRL-07", ComponentType: "controller", Mode: "clock_failure", NameDE: "Taktausfall/Taktfehler", NameEN: "Clock failure", Effect: "Zykluszeit der SPS instabil, Timing-Fehler in Sicherheitsfunktionen", DetectionHint: "Takt-Ueberwachung, Watchdog", DefaultSeverity: 8, DefaultOccurrence: 1, DefaultDetection: 3}, + {ID: "FM-CTRL-08", ComponentType: "controller", Mode: "io_card_failure", NameDE: "E/A-Karten-Ausfall", NameEN: "I/O card failure", Effect: "Eingaenge oder Ausgaenge fallen komplett aus", DetectionHint: "Kanal-Diagnose, Kurzschlusstest", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-CTRL-09", ComponentType: "controller", Mode: "cpu_overload", NameDE: "CPU-Ueberlast", NameEN: "CPU overload", Effect: "Zykluszeit ueberschritten, zeitkritische Funktionen verspaetet", DetectionHint: "Zykluszeitmonitoring, Taskauslastung", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-CTRL-10", ComponentType: "controller", Mode: "wrong_firmware_version", NameDE: "Falsche Firmware-Version", NameEN: "Wrong firmware version", Effect: "Inkompatibilitaeten, Sicherheitsfunktionen moeglicherweise unwirksam", DetectionHint: "Versionsabgleich bei Inbetriebnahme", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-CTRL-11", ComponentType: "controller", Mode: "safety_plc_discrepancy", NameDE: "Safety-SPS Kanal-Diskrepanz", NameEN: "Safety PLC channel discrepancy", Effect: "Zweikanalige Auswertung ergibt unterschiedliche Ergebnisse", DetectionHint: "Cross-Monitoring, Diagnosezyklus", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-CTRL-12", ComponentType: "controller", Mode: "common_cause_failure", NameDE: "Gemeinsame-Ursache-Ausfall (CCF)", NameEN: "Common cause failure", Effect: "Beide Kanaele der Safety-SPS fallen gleichzeitig aus", DetectionHint: "Diversitaere Hardware, getrennte Versorgung", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 8}, + {ID: "FM-CTRL-13", ComponentType: "controller", Mode: "unauthorized_access", NameDE: "Unberechtigter Zugriff auf Steuerung", NameEN: "Unauthorized access to controller", Effect: "Parameter oder Programm werden manipuliert", DetectionHint: "Zugangskontrolle, Audit-Log", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-CTRL-14", ComponentType: "controller", Mode: "emc_susceptibility", NameDE: "EMV-Empfindlichkeit", NameEN: "EMC susceptibility", Effect: "Elektromagnetische Stoerung verfaelscht Steuerungssignale", DetectionHint: "EMV-Pruefung, Schirmung", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 5}, + {ID: "FM-CTRL-15", ComponentType: "controller", Mode: "power_supply_glitch", NameDE: "Versorgungsspannung Einbruch", NameEN: "Power supply glitch", Effect: "Kurzzeitiger Spannungseinbruch fuehrt zu Steuerungsreset", DetectionHint: "USV, Spannungsueberwachung", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 2}, + + // Drive-specific + {ID: "FM-CTRL-16", ComponentType: "controller", Mode: "drive_overspeed", NameDE: "Antriebsregler Ueberdrehzahl", NameEN: "Drive overspeed", Effect: "Motor dreht ueber zulaessige Drehzahl hinaus", DetectionHint: "Sichere Drehzahlueberwachung SLS/SMS", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-CTRL-17", ComponentType: "controller", Mode: "drive_brake_failure", NameDE: "Antriebsbremse versagt", NameEN: "Drive brake failure", Effect: "Achse kann nicht gebremst werden, unkontrollierte Bewegung", DetectionHint: "Bremsentest bei Anlauf, Verschleissanzeige", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-CTRL-18", ComponentType: "controller", Mode: "drive_torque_uncontrolled", NameDE: "Unkontrolliertes Drehmoment", NameEN: "Uncontrolled torque", Effect: "Motor liefert mehr Drehmoment als erwartet", DetectionHint: "Drehmomentueberwachung, STO-Funktion", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-CTRL-19", ComponentType: "controller", Mode: "position_error_accumulation", NameDE: "Positionsfehler-Akkumulation", NameEN: "Position error accumulation", Effect: "Inkrementaler Positionsfehler summiert sich ueber Zeit", DetectionHint: "Referenzfahrt-Intervall, Absolutwertgeber", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-CTRL-20", ComponentType: "controller", Mode: "safe_state_failure", NameDE: "Versagen des sicheren Zustands", NameEN: "Safe state failure", Effect: "Maschine erreicht bei Fehler nicht den definierten sicheren Zustand", DetectionHint: "Safe-State-Test bei Inbetriebnahme", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 5}, + } +} + +// ── Actuator Failure Modes (15) ──────────────────────────────────── +func getActuatorFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-ACT-01", ComponentType: "actuator", Mode: "stuck_closed", NameDE: "Aktor blockiert (geschlossen)", NameEN: "Actuator stuck closed", Effect: "Ventil/Klappe oeffnet nicht, Prozess wird nicht freigegeben", DetectionHint: "Positionsrueckmeldung, Endlagenschalter", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-ACT-02", ComponentType: "actuator", Mode: "stuck_open", NameDE: "Aktor blockiert (offen)", NameEN: "Actuator stuck open", Effect: "Ventil/Klappe schliesst nicht, Energiezufuhr bleibt aktiv", DetectionHint: "Positionsrueckmeldung, Endlagenschalter", DefaultSeverity: 9, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-ACT-03", ComponentType: "actuator", Mode: "overload", NameDE: "Aktor-Ueberlast", NameEN: "Actuator overload", Effect: "Motor ueberhitzt, Wicklungsschaden, Ausfall", DetectionHint: "Strommessung, Thermoschutz", DefaultSeverity: 6, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-ACT-04", ComponentType: "actuator", Mode: "loss_of_holding_force", NameDE: "Haltekraftverlust", NameEN: "Loss of holding force", Effect: "Last sackt ab, unkontrollierte Bewegung durch Schwerkraft", DetectionHint: "Bremsentest, Druckueberwachung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-ACT-05", ComponentType: "actuator", Mode: "overspeed", NameDE: "Ueberdrehzahl Motor", NameEN: "Motor overspeed", Effect: "Fliehkraefte ueberschreiten zulaessige Werte", DetectionHint: "Drehzahlueberwachung, mechanische Begrenzung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-ACT-06", ComponentType: "actuator", Mode: "bearing_failure", NameDE: "Lagerschaden Motor", NameEN: "Motor bearing failure", Effect: "Erhoehte Vibration, Blockade, Ueberhitzung", DetectionHint: "Vibrationsueberwachung, Geraeuschanalyse", DefaultSeverity: 6, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-ACT-07", ComponentType: "actuator", Mode: "insulation_breakdown", NameDE: "Isolationsversagen Motorwicklung", NameEN: "Motor insulation breakdown", Effect: "Erdschluss, Kurzschluss, Stromschlagrisiko am Gehaeuse", DetectionHint: "Isolationsmessung, RCD", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-ACT-08", ComponentType: "actuator", Mode: "thermal_overload", NameDE: "Thermische Ueberlastung", NameEN: "Thermal overload", Effect: "Motor ueberhitzt, Brandgefahr bei fehlendem Thermoschutz", DetectionHint: "Temperaturueberwachung, Thermoschalter", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-ACT-09", ComponentType: "actuator", Mode: "unexpected_movement", NameDE: "Unerwartete Bewegung", NameEN: "Unexpected movement", Effect: "Aktor bewegt sich ohne Befehl, Person im Gefahrbereich gefaehrdet", DetectionHint: "Rueckmeldung mit Sollwertvergleich, STO", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 3}, + {ID: "FM-ACT-10", ComponentType: "actuator", Mode: "reduced_performance", NameDE: "Leistungsminderung", NameEN: "Reduced performance", Effect: "Kraft oder Geschwindigkeit unter Spezifikation, Prozessqualitaet sinkt", DetectionHint: "Leistungsmessung, Trendanalyse", DefaultSeverity: 4, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-ACT-11", ComponentType: "actuator", Mode: "coupling_slip", NameDE: "Kupplungsschlupf", NameEN: "Coupling slip", Effect: "Drehmoment wird nicht vollstaendig uebertragen", DetectionHint: "Soll-Ist-Vergleich Drehzahl, Schwingungsanalyse", DefaultSeverity: 5, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-ACT-12", ComponentType: "actuator", Mode: "pneumatic_cylinder_leak", NameDE: "Pneumatikzylinder-Leckage", NameEN: "Pneumatic cylinder leak", Effect: "Zylinder haelt Position nicht, langsames Absacken", DetectionHint: "Druckabfallmessung, Leckagepruefung", DefaultSeverity: 6, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-ACT-13", ComponentType: "actuator", Mode: "hydraulic_cylinder_drift", NameDE: "Hydraulikzylinder-Drift", NameEN: "Hydraulic cylinder drift", Effect: "Last sackt langsam ab trotz geschlossenem Ventil", DetectionHint: "Positionsueberwachung, Lasthalteventil", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-ACT-14", ComponentType: "actuator", Mode: "contactor_welded", NameDE: "Schuetz verschweisst", NameEN: "Contactor welded", Effect: "Motor kann nicht abgeschaltet werden, Not-Halt unwirksam", DetectionHint: "Ruecklese-Kontakt, Cross-Monitoring", DefaultSeverity: 10, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-ACT-15", ComponentType: "actuator", Mode: "valve_stiction", NameDE: "Ventil-Losbrechkraft erhoet", NameEN: "Valve stiction", Effect: "Ventil reagiert verzoegert oder gar nicht auf Steuersignal", DetectionHint: "Hubueberwachung, Stellzeit messen", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 4}, + } +} + +// ── Mechanical Failure Modes (20) ────────────────────────────────── +func getMechanicalFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-MECH-01", ComponentType: "mechanical", Mode: "fatigue_fracture", NameDE: "Ermuedungsbruch", NameEN: "Fatigue fracture", Effect: "Bauteil bricht unter Betriebslast, Teile werden herausgeschleudert", DetectionHint: "Risspruefung (zfP), Betriebsstundenzaehler", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 6}, + {ID: "FM-MECH-02", ComponentType: "mechanical", Mode: "bearing_failure", NameDE: "Lagerschaden", NameEN: "Bearing failure", Effect: "Erhoehte Reibung, Blockade, Erwaermung, Wellenbruch", DetectionHint: "Vibrationsueberwachung, Temperaturmessung", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-MECH-03", ComponentType: "mechanical", Mode: "corrosion", NameDE: "Korrosion", NameEN: "Corrosion", Effect: "Wandstaerke-Reduktion, Festigkeitsverlust, Undichtheit", DetectionHint: "Sichtpruefung, Wanddickenmessung", DefaultSeverity: 6, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-MECH-04", ComponentType: "mechanical", Mode: "loosening", NameDE: "Lockerung von Verbindungselementen", NameEN: "Loosening of fasteners", Effect: "Schrauben/Bolzen lockern sich, Bauteil loest sich", DetectionHint: "Drehmoment-Kontrolle, Sicherungselemente", DefaultSeverity: 7, DefaultOccurrence: 4, DefaultDetection: 3}, + {ID: "FM-MECH-05", ComponentType: "mechanical", Mode: "wear", NameDE: "Verschleiss", NameEN: "Wear", Effect: "Spielzunahme, Funktionsverlust, erhoehte Geraeusche", DetectionHint: "Spielmessung, Sichtpruefung, Trendanalyse", DefaultSeverity: 5, DefaultOccurrence: 5, DefaultDetection: 4}, + {ID: "FM-MECH-06", ComponentType: "mechanical", Mode: "overload_deformation", NameDE: "Ueberlast-Verformung", NameEN: "Overload deformation", Effect: "Plastische Verformung, Bauteil bleibt verbogen", DetectionHint: "Kraftueberwachung, Lastzelle", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-MECH-07", ComponentType: "mechanical", Mode: "chain_break", NameDE: "Kettenriss", NameEN: "Chain break", Effect: "Kraftuebertragung unterbrochen, Last faellt unkontrolliert", DetectionHint: "Kettenlaengungsmessung, Sichtpruefung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-MECH-08", ComponentType: "mechanical", Mode: "belt_slip_break", NameDE: "Riemenschlupf/-riss", NameEN: "Belt slip/break", Effect: "Antrieb verliert Kraftschluss oder Riemen reisst", DetectionHint: "Riemenspannung pruefen, Drehzahlvergleich", DefaultSeverity: 6, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-MECH-09", ComponentType: "mechanical", Mode: "gear_tooth_break", NameDE: "Zahnbruch im Getriebe", NameEN: "Gear tooth break", Effect: "Schlagartige Stoerung der Kraftuebertragung, Blockade", DetectionHint: "Koerperschallanalyse, Oelanalyse", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-MECH-10", ComponentType: "mechanical", Mode: "seal_failure", NameDE: "Dichtungsversagen", NameEN: "Seal failure", Effect: "Medium tritt aus, Umweltkontamination, Rutschgefahr", DetectionHint: "Leckage-Sichtpruefung, Druckabfall", DefaultSeverity: 5, DefaultOccurrence: 4, DefaultDetection: 3}, + {ID: "FM-MECH-11", ComponentType: "mechanical", Mode: "weld_crack", NameDE: "Schweissnahtriss", NameEN: "Weld crack", Effect: "Tragende Verbindung versagt, strukturelles Versagen", DetectionHint: "zfP (Ultraschall, Roentgen), Sichtpruefung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-MECH-12", ComponentType: "mechanical", Mode: "spring_break", NameDE: "Federbruch", NameEN: "Spring break", Effect: "Rueckstellkraft entfaellt, Sicherheitsfunktion versagt", DetectionHint: "Federkraftmessung, praeventiver Tausch", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-MECH-13", ComponentType: "mechanical", Mode: "structural_resonance", NameDE: "Strukturresonanz", NameEN: "Structural resonance", Effect: "Verstaerkte Schwingung, Ermuedungsbruch, Laerm", DetectionHint: "Schwingungsmessung, Modalanalyse", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-MECH-14", ComponentType: "mechanical", Mode: "misalignment", NameDE: "Fluchtungsfehler", NameEN: "Misalignment", Effect: "Erhoehter Verschleiss, Vibration, Lagerschaden", DetectionHint: "Laserausrichtung, Vibrationsmessung", DefaultSeverity: 5, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-MECH-15", ComponentType: "mechanical", Mode: "unbalance", NameDE: "Unwucht", NameEN: "Unbalance", Effect: "Vibration, Lagerschaden, Ermuedung bei Rotation", DetectionHint: "Auswuchtmaschine, Schwingungsmessung", DefaultSeverity: 5, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-MECH-16", ComponentType: "mechanical", Mode: "clamping_loss", NameDE: "Spannkraftverlust", NameEN: "Clamping force loss", Effect: "Werkstueck oder Werkzeug loest sich waehrend Bearbeitung", DetectionHint: "Spannkraftmessung, Druckueberwachung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-MECH-17", ComponentType: "mechanical", Mode: "grinding_wheel_burst", NameDE: "Schleifscheibenbruch", NameEN: "Grinding wheel burst", Effect: "Scheibenfragmente werden mit hoher Energie weggeschleudert", DetectionHint: "Klangpruefung, Drehzahlbegrenzung, Schutzhaube", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 4}, + {ID: "FM-MECH-18", ComponentType: "mechanical", Mode: "tool_break", NameDE: "Werkzeugbruch", NameEN: "Tool break", Effect: "Bruchstuecke als Projektile, Werkstueckbeschaedigung", DetectionHint: "Werkzeugbruch-Erkennung, Schutzscheibe", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-MECH-19", ComponentType: "mechanical", Mode: "guide_rail_wear", NameDE: "Fuehrungsschienen-Verschleiss", NameEN: "Guide rail wear", Effect: "Spielzunahme, Positionsungenauigkeit, Ruckeln", DetectionHint: "Spielmessung, praeventiver Tausch", DefaultSeverity: 4, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-MECH-20", ComponentType: "mechanical", Mode: "foundation_settlement", NameDE: "Fundamentsetzung", NameEN: "Foundation settlement", Effect: "Maschine steht nicht mehr eben, Ausrichtung verloren", DetectionHint: "Nivellierung pruefen, Bodenscan", DefaultSeverity: 5, DefaultOccurrence: 2, DefaultDetection: 4}, + } +} diff --git a/ai-compliance-sdk/internal/iace/failure_mode_library_ext.go b/ai-compliance-sdk/internal/iace/failure_mode_library_ext.go new file mode 100644 index 0000000..8056a06 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/failure_mode_library_ext.go @@ -0,0 +1,112 @@ +package iace + +// ── Electrical Failure Modes (15) ────────────────────────────────── +func getElectricalFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-ELEC-01", ComponentType: "electrical", Mode: "insulation_breakdown", NameDE: "Isolationsversagen", NameEN: "Insulation breakdown", Effect: "Erdschluss, Stromschlagrisiko am Gehaeuse", DetectionHint: "Isolationsmessung, RCD", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-ELEC-02", ComponentType: "electrical", Mode: "short_circuit", NameDE: "Kurzschluss", NameEN: "Short circuit", Effect: "Ueberstrom, Brand, Bauteilzerstoerung", DetectionHint: "Sicherungsautomat, Kurzschlussanzeige", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-ELEC-03", ComponentType: "electrical", Mode: "overload", NameDE: "Ueberlast Stromkreis", NameEN: "Circuit overload", Effect: "Leitungserwaermung, Isolationsschaeden, Brand", DetectionHint: "Motorschutzschalter, Strommessung", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 2}, + {ID: "FM-ELEC-04", ComponentType: "electrical", Mode: "earth_fault", NameDE: "Erdschluss", NameEN: "Earth fault", Effect: "Gefaehrliche Beruehrungsspannung am Maschinengehaeuse", DetectionHint: "RCD, Isolationswaechter", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-ELEC-05", ComponentType: "electrical", Mode: "contact_failure", NameDE: "Kontaktversagen (Uebergangswiderstand)", NameEN: "Contact failure", Effect: "Erhoehter Widerstand, Erwaermung, intermittierender Ausfall", DetectionHint: "Thermografie, Widerstandsmessung", DefaultSeverity: 6, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-ELEC-06", ComponentType: "electrical", Mode: "cable_damage", NameDE: "Kabelbeschaedigung", NameEN: "Cable damage", Effect: "Kurzschluss oder Unterbrechung, Stromschlagrisiko", DetectionHint: "Sichtpruefung, Isolationsmessung", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-ELEC-07", ComponentType: "electrical", Mode: "overvoltage", NameDE: "Ueberspannung", NameEN: "Overvoltage", Effect: "Zerstoerung elektronischer Komponenten, Datenverlust", DetectionHint: "SPD, Spannungsueberwachung", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-ELEC-08", ComponentType: "electrical", Mode: "undervoltage", NameDE: "Unterspannung", NameEN: "Undervoltage", Effect: "Steuerung faellt aus, Aktoren verlieren Haltekraft", DetectionHint: "Spannungsueberwachung, USV", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 2}, + {ID: "FM-ELEC-09", ComponentType: "electrical", Mode: "phase_loss", NameDE: "Phasenverlust (Drehstrom)", NameEN: "Phase loss", Effect: "Motor laeuft auf 2 Phasen, Ueberhitzung, Momentverlust", DetectionHint: "Phasenueberwachungsrelais", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 2}, + {ID: "FM-ELEC-10", ComponentType: "electrical", Mode: "residual_voltage", NameDE: "Restspannung nach Abschaltung", NameEN: "Residual voltage", Effect: "Stromschlag bei Wartung trotz Abschaltung", DetectionHint: "Entladewiderstaende, Spannungspruefung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-ELEC-11", ComponentType: "electrical", Mode: "pe_conductor_break", NameDE: "Schutzleiterbruch", NameEN: "PE conductor break", Effect: "Schutzerdung unwirksam, Gehaeuse wird spannungsfuehrend", DetectionHint: "Schutzleiter-Pruefung, RCD", DefaultSeverity: 10, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-ELEC-12", ComponentType: "electrical", Mode: "arc_flash", NameDE: "Lichtbogenentladung", NameEN: "Arc flash", Effect: "Explosion, Verbrennungen, Blendung", DetectionHint: "Lichtbogenerkennungsschutzschalter", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 3}, + {ID: "FM-ELEC-13", ComponentType: "electrical", Mode: "fuse_failure", NameDE: "Sicherungsversagen (nicht ausloesend)", NameEN: "Fuse failure to trip", Effect: "Ueberstromschutz unwirksam, nachgelagerte Schaeden", DetectionHint: "Selektivitaetspruefung, Schmelzsicherung pruefen", DefaultSeverity: 8, DefaultOccurrence: 1, DefaultDetection: 5}, + {ID: "FM-ELEC-14", ComponentType: "electrical", Mode: "electrostatic_discharge", NameDE: "Elektrostatische Entladung (ESD)", NameEN: "Electrostatic discharge", Effect: "Elektronik-Schaeden, Zuendquelle in Ex-Bereichen", DetectionHint: "ESD-Schutz, Erdung", DefaultSeverity: 6, DefaultOccurrence: 3, DefaultDetection: 5}, + {ID: "FM-ELEC-15", ComponentType: "electrical", Mode: "harmonic_distortion", NameDE: "Oberschwingungen im Netz", NameEN: "Harmonic distortion", Effect: "Erwaermung Transformatoren, Fehlausloesung RCD", DetectionHint: "Netzqualitaetsmessung, Oberschwingungsfilter", DefaultSeverity: 4, DefaultOccurrence: 4, DefaultDetection: 4}, + } +} + +// ── Software Failure Modes (15) ──────────────────────────────────── +func getSoftwareFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-SW-01", ComponentType: "software", Mode: "unhandled_exception", NameDE: "Unbehandelte Ausnahme", NameEN: "Unhandled exception", Effect: "Programmabsturz, Steuerung friert ein", DetectionHint: "Exception-Logging, Watchdog", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-SW-02", ComponentType: "software", Mode: "race_condition", NameDE: "Race Condition", NameEN: "Race condition", Effect: "Unvorhersehbares Timing, Ausgaben in falscher Reihenfolge", DetectionHint: "Code-Review, Concurrency-Tests", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 7}, + {ID: "FM-SW-03", ComponentType: "software", Mode: "buffer_overflow", NameDE: "Pufferueberlauf", NameEN: "Buffer overflow", Effect: "Speicherverletzung, Programmabsturz oder Code-Injection", DetectionHint: "Statische Codeanalyse, Fuzzing", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 6}, + {ID: "FM-SW-04", ComponentType: "software", Mode: "infinite_loop", NameDE: "Endlosschleife", NameEN: "Infinite loop", Effect: "Task blockiert, Watchdog loest aus, Steuerung reagiert nicht", DetectionHint: "Watchdog, Zykluszeitmonitoring", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-SW-05", ComponentType: "software", Mode: "wrong_calculation", NameDE: "Falsche Berechnung", NameEN: "Wrong calculation", Effect: "Falsche Stellgroessen, Grenzwertueberschreitung nicht erkannt", DetectionHint: "Plausibilitaetspruefung, Verifikation", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-SW-06", ComponentType: "software", Mode: "division_by_zero", NameDE: "Division durch Null", NameEN: "Division by zero", Effect: "Programmabsturz oder undefinierter Wert in Regelkreis", DetectionHint: "Defensive Programmierung, Code-Review", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-SW-07", ComponentType: "software", Mode: "integer_overflow", NameDE: "Ganzzahlueberlauf", NameEN: "Integer overflow", Effect: "Zaehler springt auf Negativwert, falsche Positionsberechnung", DetectionHint: "Statische Analyse, Grenzwerttest", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-SW-08", ComponentType: "software", Mode: "state_machine_deadlock", NameDE: "Zustandsautomat-Deadlock", NameEN: "State machine deadlock", Effect: "Maschine blockiert in undefiniertem Zustand", DetectionHint: "Zustandsdiagramm-Analyse, Timeout-Handling", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-SW-09", ComponentType: "software", Mode: "configuration_error", NameDE: "Konfigurationsfehler", NameEN: "Configuration error", Effect: "Falsche Parameter, Grenzwerte oder Ablaufsteuerung", DetectionHint: "Konfigurations-Validierung, Checksumme", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-SW-10", ComponentType: "software", Mode: "update_regression", NameDE: "Regressionsfehler nach Update", NameEN: "Update regression", Effect: "Bestehende Funktion bricht nach Software-Update", DetectionHint: "Regressionstests, Rollback-Plan", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-SW-11", ComponentType: "software", Mode: "timing_violation", NameDE: "Echtzeit-Verletzung", NameEN: "Timing violation", Effect: "Sicherheitsfunktion reagiert zu langsam", DetectionHint: "Worst-Case-Execution-Time-Analyse", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-SW-12", ComponentType: "software", Mode: "data_corruption", NameDE: "Datenverfaelschung", NameEN: "Data corruption", Effect: "Prozessdaten oder Safety-Parameter werden verfaelscht", DetectionHint: "CRC/Checksumme, diversitaere Verarbeitung", DefaultSeverity: 9, DefaultOccurrence: 1, DefaultDetection: 4}, + {ID: "FM-SW-13", ComponentType: "software", Mode: "resource_leak", NameDE: "Ressourcen-Leck", NameEN: "Resource leak", Effect: "Speicher oder Handles gehen ueber Zeit verloren, System wird langsam", DetectionHint: "Langzeit-Monitoring, Heap-Analyse", DefaultSeverity: 5, DefaultOccurrence: 3, DefaultDetection: 6}, + {ID: "FM-SW-14", ComponentType: "software", Mode: "wrong_unit_conversion", NameDE: "Falsche Einheitenumrechnung", NameEN: "Wrong unit conversion", Effect: "Werte werden falsch interpretiert (mm vs inch, bar vs psi)", DetectionHint: "Unit-Tests, Plausibilitaetspruefung", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-SW-15", ComponentType: "software", Mode: "log_overflow", NameDE: "Log-Speicher voll", NameEN: "Log overflow", Effect: "Diagnosedaten gehen verloren, Fehleranalyse unmoeglich", DetectionHint: "Log-Rotation, Speicherueberwachung", DefaultSeverity: 3, DefaultOccurrence: 4, DefaultDetection: 3}, + } +} + +// ── Hydraulic/Pneumatic Failure Modes (15) ────────────────────────── +func getFluidFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-FLU-01", ComponentType: "hydraulic", Mode: "hose_burst", NameDE: "Schlauchplatzer", NameEN: "Hose burst", Effect: "Unkontrollierter Medienaustritt, Peitscheneffekt, Hautinjektion", DetectionHint: "Druckabfallerkennung, Schlauchbruchventil", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-FLU-02", ComponentType: "hydraulic", Mode: "valve_stuck", NameDE: "Ventil blockiert", NameEN: "Valve stuck", Effect: "Hydraulikzylinder bewegt sich nicht oder haelt nicht", DetectionHint: "Stellungsueberwachung, Druckueberwachung", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-FLU-03", ComponentType: "hydraulic", Mode: "seal_leak", NameDE: "Dichtungsleckage", NameEN: "Seal leakage", Effect: "Druckverlust, Oelkontamination, Rutschgefahr", DetectionHint: "Sichtpruefung, Fuellstandsueberwachung", DefaultSeverity: 5, DefaultOccurrence: 5, DefaultDetection: 3}, + {ID: "FM-FLU-04", ComponentType: "hydraulic", Mode: "oil_contamination", NameDE: "Oelverschmutzung", NameEN: "Oil contamination", Effect: "Vorzeitiger Komponentenverschleiss, Ventilversagen", DetectionHint: "Oelanalyse, Filterueberwachung", DefaultSeverity: 6, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-FLU-05", ComponentType: "hydraulic", Mode: "pump_cavitation", NameDE: "Pumpenkavitation", NameEN: "Pump cavitation", Effect: "Laufradschaeden, Druckverlust, Geraeusche", DetectionHint: "Saugdruckueberwachung, Geraeuschanalyse", DefaultSeverity: 6, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-FLU-06", ComponentType: "hydraulic", Mode: "accumulator_failure", NameDE: "Speicherausfall (Hydrospeicher)", NameEN: "Accumulator failure", Effect: "Druckpolster fehlt, Druckspitzen nicht gedaempft", DetectionHint: "Vorfuelldruck pruefen, Blasenspeicher-Test", DefaultSeverity: 6, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-FLU-07", ComponentType: "hydraulic", Mode: "pressure_relief_stuck", NameDE: "Druckbegrenzungsventil klemmt", NameEN: "Pressure relief valve stuck", Effect: "Maximaldruck wird ueberschritten, Bersten moeglich", DetectionHint: "Regelmassige Funktionspruefung", DefaultSeverity: 10, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-FLU-08", ComponentType: "pneumatic", Mode: "air_leak", NameDE: "Druckluftleckage", NameEN: "Air leak", Effect: "Druckverlust, Zylinder haelt Position nicht", DetectionHint: "Leckagesuchgeraet, Druckabfalltest", DefaultSeverity: 4, DefaultOccurrence: 5, DefaultDetection: 3}, + {ID: "FM-FLU-09", ComponentType: "pneumatic", Mode: "moisture_in_air", NameDE: "Feuchtigkeit in Druckluft", NameEN: "Moisture in compressed air", Effect: "Korrosion, Ventilversagen, Eisbildung", DetectionHint: "Kondensatableiter pruefen, Taupunktmessung", DefaultSeverity: 5, DefaultOccurrence: 4, DefaultDetection: 4}, + {ID: "FM-FLU-10", ComponentType: "pneumatic", Mode: "compressor_overheating", NameDE: "Kompressor-Ueberhitzung", NameEN: "Compressor overheating", Effect: "Oeldampf im Druckluftnetz, Brandgefahr", DetectionHint: "Temperaturueberwachung, Thermostat", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-FLU-11", ComponentType: "hydraulic", Mode: "cylinder_drift", NameDE: "Zylinderdrift (Lastabsacken)", NameEN: "Cylinder drift", Effect: "Last sackt langsam ab, Quetschgefahr", DetectionHint: "Positionsueberwachung, Lasthalteventil", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-FLU-12", ComponentType: "hydraulic", Mode: "filter_clogging", NameDE: "Filterverstopfung", NameEN: "Filter clogging", Effect: "Druckdifferenz steigt, Bypass oeffnet, ungefilterte Partikel", DetectionHint: "Differenzdruckschalter, Wartungsintervall", DefaultSeverity: 5, DefaultOccurrence: 4, DefaultDetection: 2}, + {ID: "FM-FLU-13", ComponentType: "hydraulic", Mode: "pressure_surge", NameDE: "Druckstoss (Joukowsky)", NameEN: "Pressure surge", Effect: "Kurzfristige Druckspitze schaedigt Leitungen und Armaturen", DetectionHint: "Druckstossdaempfer, langsam schliessende Ventile", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 5}, + {ID: "FM-FLU-14", ComponentType: "hydraulic", Mode: "tank_overflow", NameDE: "Tankueberlauf", NameEN: "Tank overflow", Effect: "Oelverlust, Umweltkontamination, Rutschgefahr", DetectionHint: "Fuellstandsueberwachung mit Alarm", DefaultSeverity: 5, DefaultOccurrence: 3, DefaultDetection: 2}, + {ID: "FM-FLU-15", ComponentType: "pneumatic", Mode: "quick_exhaust_failure", NameDE: "Schnellentlueftungsventil versagt", NameEN: "Quick exhaust valve failure", Effect: "Zylinder faehrt langsam zurueck, Zykluszeit steigt", DetectionHint: "Positionszeit-Ueberwachung", DefaultSeverity: 4, DefaultOccurrence: 3, DefaultDetection: 3}, + } +} + +// ── Safety Device Failure Modes (15) ─────────────────────────────── +func getSafetyDeviceFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-SAF-01", ComponentType: "safety_device", Mode: "failure_to_trip", NameDE: "Schutzeinrichtung loest nicht aus", NameEN: "Failure to trip", Effect: "Gefahrsituation wird nicht erkannt, Person ungeschuetzt", DetectionHint: "Proof-Test, Funktionspruefung", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 5}, + {ID: "FM-SAF-02", ComponentType: "safety_device", Mode: "spurious_trip", NameDE: "Fehlausloesung Schutzeinrichtung", NameEN: "Spurious trip", Effect: "Unnoetiger Maschinenstopp, Produktionsverlust, Fehlbedienung", DetectionHint: "Alarmstatistik, Diagnostik", DefaultSeverity: 3, DefaultOccurrence: 4, DefaultDetection: 2}, + {ID: "FM-SAF-03", ComponentType: "safety_device", Mode: "degraded_response_time", NameDE: "Verlaengerte Reaktionszeit", NameEN: "Degraded response time", Effect: "Maschine stoppt zu spaet, Person wird erfasst", DetectionHint: "Reaktionszeitmessung, Proof-Test", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 6}, + {ID: "FM-SAF-04", ComponentType: "safety_device", Mode: "guard_bypass", NameDE: "Schutzeinrichtung umgangen", NameEN: "Guard bypass", Effect: "Schutzfunktion komplett unwirksam", DetectionHint: "Manipulationserkennung, Codierung", DefaultSeverity: 10, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-SAF-05", ComponentType: "safety_device", Mode: "interlock_wear", NameDE: "Verriegelungs-Verschleiss", NameEN: "Interlock wear", Effect: "Verriegelung greift nicht mehr zuverlaessig", DetectionHint: "Schaltspielzaehler, praeventiver Tausch", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-SAF-06", ComponentType: "safety_device", Mode: "emergency_stop_defect", NameDE: "Not-Halt-Defekt", NameEN: "Emergency stop defect", Effect: "Not-Halt-Taster funktionslos, kein sofortiger Stopp moeglich", DetectionHint: "Taeglicher Funktionstest", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 2}, + {ID: "FM-SAF-07", ComponentType: "safety_device", Mode: "safety_relay_stuck", NameDE: "Sicherheitsrelais klebt", NameEN: "Safety relay stuck", Effect: "Zwangsgefuehrter Kontakt oeffnet nicht, Abschaltung versagt", DetectionHint: "Zwangsoeffnungspruefung, Cross-Monitoring", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 3}, + {ID: "FM-SAF-08", ComponentType: "safety_device", Mode: "brake_wear", NameDE: "Bremsenverschleiss", NameEN: "Brake wear", Effect: "Bremswirkung reduziert, Nachlaufweg verlaengert", DetectionHint: "Nachlaufweg-Messung, Bremsmoment-Test", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-SAF-09", ComponentType: "safety_device", Mode: "muting_error", NameDE: "Muting-Fehler (Lichtvorhang)", NameEN: "Muting error", Effect: "Lichtvorhang wird im falschen Moment stummgeschaltet", DetectionHint: "Muting-Logik-Test, Timing-Pruefung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 5}, + {ID: "FM-SAF-10", ComponentType: "safety_device", Mode: "common_cause_failure", NameDE: "Gemeinsame-Ursache-Ausfall (CCF)", NameEN: "Common cause failure", Effect: "Beide redundante Kanaele fallen gleichzeitig aus", DetectionHint: "Diversitaet, getrennte Versorgung, DC-Anteil", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 8}, + {ID: "FM-SAF-11", ComponentType: "safety_device", Mode: "guard_misaligned", NameDE: "Schutzeinrichtung falsch ausgerichtet", NameEN: "Guard misaligned", Effect: "Sicherheitsabstand nicht eingehalten, Zugang zum Gefahrbereich", DetectionHint: "Ausrichtungspruefung, Testkoerper", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-SAF-12", ComponentType: "safety_device", Mode: "safety_function_not_tested", NameDE: "Sicherheitsfunktion nicht getestet", NameEN: "Safety function not tested", Effect: "Unerkannter Defekt, Schutzwirkung ungesichert", DetectionHint: "Proof-Test-Plan, Testprotokoll", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 7}, + {ID: "FM-SAF-13", ComponentType: "safety_device", Mode: "pl_degradation", NameDE: "PL/SIL-Degradation", NameEN: "PL/SIL degradation", Effect: "Performance Level sinkt unter erforderlichen Wert", DetectionHint: "PL-Validierung, DC-Berechnung", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 6}, + {ID: "FM-SAF-14", ComponentType: "safety_device", Mode: "enabling_device_failure", NameDE: "Zustimmschalter-Defekt", NameEN: "Enabling device failure", Effect: "Teach-Betrieb ohne Totmann-Sicherung moeglich", DetectionHint: "Funktionspruefung 3-Stufen-Schalter", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-SAF-15", ComponentType: "safety_device", Mode: "restart_interlock_bypass", NameDE: "Wiederanlaufsperre umgangen", NameEN: "Restart interlock bypass", Effect: "Maschine startet automatisch nach Not-Halt ohne Quittierung", DetectionHint: "Wiederanlauf-Test, Softwarepruefung", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 4}, + } +} + +// ── Network Failure Modes (10) ───────────────────────────────────── +func getNetworkFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-NET-01", ComponentType: "network", Mode: "packet_loss", NameDE: "Paketverlust", NameEN: "Packet loss", Effect: "Steuerbefehle gehen verloren, Aktor reagiert verzoegert", DetectionHint: "Netzwerk-Monitoring, Retry-Mechanismus", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-NET-02", ComponentType: "network", Mode: "latency_spike", NameDE: "Latenz-Spitze", NameEN: "Latency spike", Effect: "Echtzeitfaehigkeit verloren, Sicherheitsfunktion reagiert zu spaet", DetectionHint: "Jitter-Monitoring, QoS", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 4}, + {ID: "FM-NET-03", ComponentType: "network", Mode: "network_disconnect", NameDE: "Netzwerktrennung", NameEN: "Network disconnect", Effect: "Steuerung verliert Verbindung zu Peripherie", DetectionHint: "Link-Ueberwachung, Heartbeat", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 2}, + {ID: "FM-NET-04", ComponentType: "network", Mode: "man_in_the_middle", NameDE: "Man-in-the-Middle-Angriff", NameEN: "Man-in-the-middle attack", Effect: "Steuerbefehle werden abgefangen oder manipuliert", DetectionHint: "Verschluesselung, Integritaetspruefung", DefaultSeverity: 10, DefaultOccurrence: 1, DefaultDetection: 7}, + {ID: "FM-NET-05", ComponentType: "network", Mode: "broadcast_storm", NameDE: "Broadcast-Sturm", NameEN: "Broadcast storm", Effect: "Netzwerk ueberlastet, alle Kommunikation blockiert", DetectionHint: "Storm-Control, VLAN-Segmentierung", DefaultSeverity: 7, DefaultOccurrence: 2, DefaultDetection: 3}, + {ID: "FM-NET-06", ComponentType: "network", Mode: "switch_failure", NameDE: "Switch-Ausfall", NameEN: "Switch failure", Effect: "Netzwerksegment komplett offline", DetectionHint: "Redundanter Switch, Link-Aggregation", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 2}, + {ID: "FM-NET-07", ComponentType: "network", Mode: "dns_failure", NameDE: "DNS-Ausfall", NameEN: "DNS failure", Effect: "Namensaufloesung versagt, Cloud-Dienste nicht erreichbar", DetectionHint: "Lokale DNS-Cache, IP-Fallback", DefaultSeverity: 4, DefaultOccurrence: 3, DefaultDetection: 2}, + {ID: "FM-NET-08", ComponentType: "network", Mode: "certificate_expiry", NameDE: "Zertifikat abgelaufen", NameEN: "Certificate expiry", Effect: "TLS-Verbindungen werden abgelehnt, Fernwartung unmoeglich", DetectionHint: "Zertifikats-Monitoring, automatische Erneuerung", DefaultSeverity: 5, DefaultOccurrence: 3, DefaultDetection: 3}, + {ID: "FM-NET-09", ComponentType: "network", Mode: "protocol_mismatch", NameDE: "Protokoll-Inkompatibilitaet", NameEN: "Protocol mismatch", Effect: "Geraete koennen nicht kommunizieren nach Firmware-Update", DetectionHint: "Versionsmatrix, Kompatibilitaetstest", DefaultSeverity: 6, DefaultOccurrence: 2, DefaultDetection: 4}, + {ID: "FM-NET-10", ComponentType: "network", Mode: "firewall_misconfiguration", NameDE: "Firewall-Fehlkonfiguration", NameEN: "Firewall misconfiguration", Effect: "Safety-Traffic blockiert oder unsicherer Traffic erlaubt", DetectionHint: "Firewall-Regelaudit, Penetrationstest", DefaultSeverity: 8, DefaultOccurrence: 2, DefaultDetection: 5}, + } +} + +// ── AI/ML Failure Modes (5) ──────────────────────────────────────── +func getAIFailureModes() []FailureModeEntry { + return []FailureModeEntry{ + {ID: "FM-AI-01", ComponentType: "ai_model", Mode: "model_drift", NameDE: "Modell-Drift", NameEN: "Model drift", Effect: "KI-Modell verliert Genauigkeit ueber Zeit durch veraenderte Daten", DetectionHint: "Performance-Monitoring, Referenzdaten-Test", DefaultSeverity: 7, DefaultOccurrence: 4, DefaultDetection: 5}, + {ID: "FM-AI-02", ComponentType: "ai_model", Mode: "adversarial_input", NameDE: "Adversarial Input", NameEN: "Adversarial input", Effect: "Gezielt manipulierte Eingaben fuehren zu Fehlklassifikation", DetectionHint: "Input-Validierung, Adversarial-Training", DefaultSeverity: 9, DefaultOccurrence: 2, DefaultDetection: 7}, + {ID: "FM-AI-03", ComponentType: "ai_model", Mode: "bias", NameDE: "Systematische Verzerrung (Bias)", NameEN: "Systematic bias", Effect: "Modell diskriminiert bestimmte Eingabemuster systematisch", DetectionHint: "Fairness-Metriken, diverse Testdaten", DefaultSeverity: 7, DefaultOccurrence: 3, DefaultDetection: 6}, + {ID: "FM-AI-04", ComponentType: "ai_model", Mode: "confidence_miscalibration", NameDE: "Konfidenz-Fehlkalibrierung", NameEN: "Confidence miscalibration", Effect: "Modell gibt hohe Konfidenz bei falschen Vorhersagen", DetectionHint: "Kalibrierungskurve, Expected Calibration Error", DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 6}, + {ID: "FM-AI-05", ComponentType: "ai_model", Mode: "training_data_poisoning", NameDE: "Training-Daten-Vergiftung", NameEN: "Training data poisoning", Effect: "Manipulierte Trainingsdaten fuehren zu fehlerhaftem Modell", DetectionHint: "Datenherkunft pruefen, Anomalieerkennung", DefaultSeverity: 9, DefaultOccurrence: 1, DefaultDetection: 8}, + } +} diff --git a/ai-compliance-sdk/internal/iace/failure_mode_test.go b/ai-compliance-sdk/internal/iace/failure_mode_test.go new file mode 100644 index 0000000..49f5746 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/failure_mode_test.go @@ -0,0 +1,124 @@ +package iace + +import "testing" + +func TestFailureModeLibrary_Count(t *testing.T) { + fms := GetFailureModeLibrary() + if len(fms) < 140 { + t.Errorf("expected at least 140 failure modes, got %d", len(fms)) + } + t.Logf("Total failure modes: %d", len(fms)) +} + +func TestFailureModeLibrary_UniqueIDs(t *testing.T) { + seen := make(map[string]bool) + for _, fm := range GetFailureModeLibrary() { + if seen[fm.ID] { + t.Errorf("duplicate failure mode ID: %s", fm.ID) + } + seen[fm.ID] = true + } +} + +func TestFailureModeLibrary_ValidComponentTypes(t *testing.T) { + validTypes := map[string]bool{ + "sensor": true, "controller": true, "actuator": true, + "mechanical": true, "electrical": true, "software": true, + "hydraulic": true, "pneumatic": true, "safety_device": true, + "network": true, "ai_model": true, + } + for _, fm := range GetFailureModeLibrary() { + if !validTypes[fm.ComponentType] { + t.Errorf("FM %s has invalid ComponentType: %s", fm.ID, fm.ComponentType) + } + } +} + +func TestFailureModeLibrary_NonEmptyFields(t *testing.T) { + for _, fm := range GetFailureModeLibrary() { + if fm.NameDE == "" { + t.Errorf("FM %s has empty NameDE", fm.ID) + } + if fm.Effect == "" { + t.Errorf("FM %s has empty Effect", fm.ID) + } + if fm.DefaultSeverity < 1 || fm.DefaultSeverity > 10 { + t.Errorf("FM %s has invalid Severity: %d", fm.ID, fm.DefaultSeverity) + } + if fm.DefaultOccurrence < 1 || fm.DefaultOccurrence > 10 { + t.Errorf("FM %s has invalid Occurrence: %d", fm.ID, fm.DefaultOccurrence) + } + if fm.DefaultDetection < 1 || fm.DefaultDetection > 10 { + t.Errorf("FM %s has invalid Detection: %d", fm.ID, fm.DefaultDetection) + } + } +} + +func TestFailureModeLibrary_ComponentTypeDistribution(t *testing.T) { + counts := make(map[string]int) + for _, fm := range GetFailureModeLibrary() { + counts[fm.ComponentType]++ + } + for ct, n := range counts { + t.Logf(" %s: %d failure modes", ct, n) + } + if len(counts) < 8 { + t.Errorf("expected at least 8 component types, got %d", len(counts)) + } +} + +func TestRPZ_Calculation(t *testing.T) { + fm := FailureModeEntry{DefaultSeverity: 8, DefaultOccurrence: 3, DefaultDetection: 4} + rpz := fm.CalculateRPZ() + if rpz != 96 { + t.Errorf("expected RPZ 96 (8*3*4), got %d", rpz) + } +} + +func TestRPZ_Maximum(t *testing.T) { + fm := FailureModeEntry{DefaultSeverity: 10, DefaultOccurrence: 10, DefaultDetection: 10} + rpz := fm.CalculateRPZ() + if rpz != 1000 { + t.Errorf("expected RPZ 1000 (10*10*10), got %d", rpz) + } +} + +func TestRPZ_Threshold(t *testing.T) { + below := FailureModeEntry{DefaultSeverity: 5, DefaultOccurrence: 2, DefaultDetection: 3} + above := FailureModeEntry{DefaultSeverity: 8, DefaultOccurrence: 4, DefaultDetection: 4} + + if below.CalculateRPZ() >= RPZThresholdAction { + t.Error("RPZ 30 should be below threshold 100") + } + if above.CalculateRPZ() < RPZThresholdAction { + t.Errorf("RPZ %d should be above threshold 100", above.CalculateRPZ()) + } +} + +func TestPatternEngine_FailureMode_NilFiresAlways(t *testing.T) { + engine := NewPatternEngine() + // Without FailureModes in input — all patterns should fire normally + result := engine.Match(MatchInput{ + ComponentLibraryIDs: []string{"C001"}, + EnergySourceIDs: []string{"EN01"}, + }) + if len(result.MatchedPatterns) == 0 { + t.Fatal("expected patterns without failure mode filter") + } +} + +func TestFailureModeLibrary_RPZDistribution(t *testing.T) { + actionRequired := 0 + critical := 0 + for _, fm := range GetFailureModeLibrary() { + rpz := fm.CalculateRPZ() + if rpz >= RPZThresholdAction { + actionRequired++ + } + if rpz >= 200 { + critical++ + } + } + t.Logf("RPZ distribution: %d action required (>=100), %d critical (>=200), of %d total", + actionRequired, critical, len(GetFailureModeLibrary())) +} diff --git a/ai-compliance-sdk/internal/iace/hazard_pattern_types.go b/ai-compliance-sdk/internal/iace/hazard_pattern_types.go index 5c4ad74..ec50294 100644 --- a/ai-compliance-sdk/internal/iace/hazard_pattern_types.go +++ b/ai-compliance-sdk/internal/iace/hazard_pattern_types.go @@ -50,6 +50,10 @@ type HazardPattern struct { // "hazard" = source only, "hazardous_situation" = person exposed, "harm" = injury. // Empty = default (hazardous_situation). GeneratedHazardType string `json:"generated_hazard_type,omitempty"` + // RequiredFailureModes restricts this pattern to fire only when at least one + // of the listed failure modes is relevant (by ComponentType match against project components). + // Empty/nil = fires regardless of failure modes (backwards compatible). + RequiredFailureModes []string `json:"required_failure_modes,omitempty"` } // Standard human roles for machinery interaction (ISO 12100 + BetrSichV). diff --git a/ai-compliance-sdk/internal/iace/models.go b/ai-compliance-sdk/internal/iace/models.go index fc58b94..1a69638 100644 --- a/ai-compliance-sdk/internal/iace/models.go +++ b/ai-compliance-sdk/internal/iace/models.go @@ -88,6 +88,33 @@ func DeriveHazardType(h *Hazard) string { return DefaultHazardType } +// FailureModeEntry represents a potential failure mode for a component type. +// Used for FMEA (Failure Mode and Effects Analysis) — the chain is: +// Component → FailureMode → HazardousSituation → Harm. +type FailureModeEntry struct { + ID string `json:"id"` // e.g. "FM-SEN-01" + ComponentType string `json:"component_type"` // e.g. "sensor", "controller" + Mode string `json:"mode"` // e.g. "loss_of_signal", "drift" + NameDE string `json:"name_de"` + NameEN string `json:"name_en"` + Effect string `json:"effect"` // System-level effect + DetectionHint string `json:"detection_hint"` // How to detect this failure + // FMEA scores (each 1-10) + DefaultSeverity int `json:"default_severity"` // Impact severity + DefaultOccurrence int `json:"default_occurrence"` // How often it occurs + DefaultDetection int `json:"default_detection"` // Detectability (10=undetectable, 1=immediately detectable) +} + +// CalculateRPZ computes the Risk Priority Number for a failure mode. +// RPZ = Severity × Occurrence × Detection. Range: 1-1000. +// RPZ > 100: action required. RPZ > 200: critical. +func (fm *FailureModeEntry) CalculateRPZ() int { + return fm.DefaultSeverity * fm.DefaultOccurrence * fm.DefaultDetection +} + +// RPZThresholdAction is the RPZ value above which corrective action is required. +const RPZThresholdAction = 100 + // AssessmentType represents the type of risk assessment type AssessmentType string diff --git a/ai-compliance-sdk/internal/iace/pattern_engine.go b/ai-compliance-sdk/internal/iace/pattern_engine.go index 1c8aef0..d2ef7c1 100644 --- a/ai-compliance-sdk/internal/iace/pattern_engine.go +++ b/ai-compliance-sdk/internal/iace/pattern_engine.go @@ -17,6 +17,9 @@ type MatchInput struct { // HumanRoles are the human roles interacting with the machine in this project. // Used to filter patterns that only apply to specific roles (e.g. programmer, maintenance_tech). HumanRoles []string `json:"human_roles,omitempty"` + // FailureModes are the active failure mode IDs relevant for this project. + // Used to filter patterns that require specific failure modes. + FailureModes []string `json:"failure_modes,omitempty"` } // MatchOutput contains the results of pattern matching. @@ -56,8 +59,9 @@ type PatternMatch struct { RequiresExpert bool `json:"requires_expert,omitempty"` OperationalStates []string `json:"operational_states,omitempty"` StateTransitions []string `json:"state_transitions,omitempty"` - HumanRoles []string `json:"human_roles,omitempty"` - GeneratedHazardType string `json:"generated_hazard_type,omitempty"` + HumanRoles []string `json:"human_roles,omitempty"` + GeneratedHazardType string `json:"generated_hazard_type,omitempty"` + MatchedFailureModes []string `json:"matched_failure_modes,omitempty"` } // HazardSuggestion is a suggested hazard from pattern matching. @@ -209,6 +213,17 @@ func (e *PatternEngine) Match(input MatchInput) *MatchOutput { reasons = append(reasons, MatchReason{Type: "human_role", Tag: r, Met: roleSet[r]}) } } + var matchedFMs []string + if len(p.RequiredFailureModes) > 0 { + fmSet := toSet(input.FailureModes) + for _, fm := range p.RequiredFailureModes { + met := fmSet[fm] + reasons = append(reasons, MatchReason{Type: "failure_mode", Tag: fm, Met: met}) + if met { + matchedFMs = append(matchedFMs, fm) + } + } + } matchedPatterns = append(matchedPatterns, PatternMatch{ PatternID: p.ID, @@ -230,6 +245,7 @@ func (e *PatternEngine) Match(input MatchInput) *MatchOutput { StateTransitions: p.StateTransitions, HumanRoles: p.HumanRoles, GeneratedHazardType: p.GeneratedHazardType, + MatchedFailureModes: matchedFMs, }) for _, cat := range p.GeneratedHazardCats { @@ -382,6 +398,21 @@ func patternMatches(p HazardPattern, tagSet map[string]bool, input MatchInput) b } } + // If pattern requires specific failure modes, at least one must match. + if len(p.RequiredFailureModes) > 0 && len(input.FailureModes) > 0 { + found := false + fmSet := toSet(input.FailureModes) + for _, fm := range p.RequiredFailureModes { + if fmSet[fm] { + found = true + break + } + } + if !found { + return false + } + } + return true }