feat(iace): integrate ISO 12100 machine risk model with 4-factor assessment
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 36s
CI/CD / test-python-backend-compliance (push) Successful in 36s
CI/CD / test-python-document-crawler (push) Successful in 22s
CI/CD / test-python-dsms-gateway (push) Successful in 18s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Successful in 2s

Add dual-mode risk engine: legacy S×E×P (avoidance=0) and ISO mode S×F×P×A
(avoidance>=1) with new thresholds (low/medium/high/very_high/not_acceptable).

- 150+ hazard library entries across 28 categories incl. physical hazards
  (mechanical, electrical, thermal, pneumatic/hydraulic, noise/vibration,
  ergonomic, material/environmental)
- 160-entry protective measures library with 3-step hierarchy validation
  (design → protective → information)
- 25 lifecycle phases, 20 affected person roles, 50 evidence types
- 10 verification methods (expanded from 7)
- New API endpoints: lifecycle-phases, roles, evidence-types,
  protective-measures-library, validate-mitigation-hierarchy
- DB migrations 018+019 for extended schema
- Frontend: 4-slider risk assessment, hierarchy warnings, measures library modal
- MkDocs wiki updated with ISO mode docs and legal notice (no norm text)

All content uses original wording — norms referenced as methodology only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-15 23:13:41 +01:00
parent c8fd9cc780
commit c7651796c9
15 changed files with 3708 additions and 479 deletions

View File

@@ -10,12 +10,21 @@ interface Hazard {
component_id: string | null
component_name: string | null
category: string
sub_category: string
status: string
severity: number
exposure: number
probability: number
avoidance: number
r_inherent: number
risk_level: string
machine_module: string
lifecycle_phase: string
trigger_event: string
affected_person: string
possible_harm: string
hazardous_zone: string
review_status: string
created_at: string
}
@@ -24,31 +33,71 @@ interface LibraryHazard {
name: string
description: string
category: string
sub_category: string
default_severity: number
default_exposure: number
default_probability: number
default_avoidance: number
typical_causes: string[]
typical_harm: string
relevant_lifecycle_phases: string[]
recommended_measures_design: string[]
recommended_measures_technical: string[]
recommended_measures_information: string[]
}
interface LifecyclePhase {
id: string
label_de: string
label_en: string
sort_order: number
}
interface RoleInfo {
id: string
label_de: string
label_en: string
sort_order: number
}
// ISO 12100 Hazard Categories (A-J)
const HAZARD_CATEGORIES = [
'mechanical', 'electrical', 'thermal', 'noise', 'vibration',
'radiation', 'material', 'ergonomic', 'software', 'ai_specific',
'cybersecurity', 'functional_safety', 'environmental',
'mechanical', 'electrical', 'thermal',
'pneumatic_hydraulic', 'noise_vibration', 'ergonomic',
'material_environmental', 'software_control', 'cyber_network',
'ai_specific',
]
const CATEGORY_LABELS: Record<string, string> = {
mechanical: 'Mechanisch',
electrical: 'Elektrisch',
thermal: 'Thermisch',
noise: 'Laerm',
vibration: 'Vibration',
radiation: 'Strahlung',
material: 'Stoffe/Materialien',
ergonomic: 'Ergonomie',
software: 'Software',
ai_specific: 'KI-spezifisch',
cybersecurity: 'Cybersecurity',
functional_safety: 'Funktionale Sicherheit',
environmental: 'Umgebung',
// Primary categories (new naming)
mechanical: 'A. Mechanisch',
electrical: 'B. Elektrisch',
thermal: 'C. Thermisch',
pneumatic_hydraulic: 'D. Pneumatik/Hydraulik',
noise_vibration: 'E. Laerm/Vibration',
ergonomic: 'F. Ergonomie',
material_environmental: 'G. Stoffe/Umwelt',
software_control: 'H. Software/Steuerung',
cyber_network: 'I. Cyber/Netzwerk',
ai_specific: 'J. KI-spezifisch',
// Legacy names (backward compat for existing data)
mechanical_hazard: 'A. Mechanisch',
electrical_hazard: 'B. Elektrisch',
thermal_hazard: 'C. Thermisch',
software_fault: 'H. Software/Steuerung',
safety_function_failure: 'H. Sicherheitsfunktionen',
false_classification: 'J. KI-spezifisch',
unauthorized_access: 'I. Cyber/Netzwerk',
configuration_error: 'H. Konfiguration',
hmi_error: 'H. HMI-Fehler',
integration_error: 'H. Integration',
communication_failure: 'I. Kommunikation',
sensor_spoofing: 'I. Sensormanipulation',
model_drift: 'J. Modelldrift',
data_poisoning: 'J. Daten-Poisoning',
emc_hazard: 'B. EMV',
maintenance_hazard: 'F. Wartung',
update_failure: 'H. Update-Fehler',
}
const STATUS_LABELS: Record<string, string> = {
@@ -59,8 +108,18 @@ const STATUS_LABELS: Record<string, string> = {
closed: 'Geschlossen',
}
const REVIEW_STATUS_LABELS: Record<string, string> = {
draft: 'Entwurf',
in_review: 'In Pruefung',
reviewed: 'Geprueft',
approved: 'Freigegeben',
rejected: 'Abgelehnt',
}
function getRiskColor(level: string): string {
switch (level) {
case 'not_acceptable': return 'bg-red-200 text-red-900 border-red-300'
case 'very_high': return 'bg-red-100 text-red-700 border-red-200'
case 'critical': return 'bg-red-100 text-red-700 border-red-200'
case 'high': return 'bg-orange-100 text-orange-700 border-orange-200'
case 'medium': return 'bg-yellow-100 text-yellow-700 border-yellow-200'
@@ -69,7 +128,17 @@ function getRiskColor(level: string): string {
}
}
function getRiskLevel(r: number): string {
// ISO 12100 mode risk levels (S×F×P×A, max 625)
function getRiskLevelISO(r: number): string {
if (r > 300) return 'not_acceptable'
if (r >= 151) return 'very_high'
if (r >= 61) return 'high'
if (r >= 21) return 'medium'
return 'low'
}
// Legacy mode (S×E×P, max 125)
function getRiskLevelLegacy(r: number): string {
if (r >= 100) return 'critical'
if (r >= 50) return 'high'
if (r >= 20) return 'medium'
@@ -78,6 +147,8 @@ function getRiskLevel(r: number): string {
function getRiskLevelLabel(level: string): string {
switch (level) {
case 'not_acceptable': return 'Nicht akzeptabel'
case 'very_high': return 'Sehr hoch'
case 'critical': return 'Kritisch'
case 'high': return 'Hoch'
case 'medium': return 'Mittel'
@@ -94,6 +165,21 @@ function RiskBadge({ level }: { level: string }) {
)
}
function ReviewStatusBadge({ status }: { status: string }) {
const colors: Record<string, string> = {
draft: 'bg-gray-100 text-gray-600 border-gray-200',
in_review: 'bg-blue-100 text-blue-600 border-blue-200',
reviewed: 'bg-indigo-100 text-indigo-600 border-indigo-200',
approved: 'bg-green-100 text-green-600 border-green-200',
rejected: 'bg-red-100 text-red-600 border-red-200',
}
return (
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium border ${colors[status] || colors.draft}`}>
{REVIEW_STATUS_LABELS[status] || status}
</span>
)
}
interface HazardFormData {
name: string
description: string
@@ -102,27 +188,52 @@ interface HazardFormData {
severity: number
exposure: number
probability: number
avoidance: number
lifecycle_phase: string
trigger_event: string
affected_person: string
possible_harm: string
hazardous_zone: string
machine_module: string
}
function HazardForm({
onSubmit,
onCancel,
lifecyclePhases,
roles,
}: {
onSubmit: (data: HazardFormData) => void
onCancel: () => void
lifecyclePhases: LifecyclePhase[]
roles: RoleInfo[]
}) {
const [formData, setFormData] = useState<HazardFormData>({
name: '',
description: '',
category: 'mechanical',
category: 'mechanical_hazard',
component_id: '',
severity: 3,
exposure: 3,
probability: 3,
avoidance: 3,
lifecycle_phase: '',
trigger_event: '',
affected_person: '',
possible_harm: '',
hazardous_zone: '',
machine_module: '',
})
const rInherent = formData.severity * formData.exposure * formData.probability
const riskLevel = getRiskLevel(rInherent)
const [showExtended, setShowExtended] = useState(false)
// ISO 12100 mode: S × F × P × A when avoidance is set
const isISOMode = formData.avoidance > 0
const rInherent = isISOMode
? formData.severity * formData.exposure * formData.probability * formData.avoidance
: formData.severity * formData.exposure * formData.probability
const riskLevel = isISOMode ? getRiskLevelISO(rInherent) : getRiskLevelLegacy(rInherent)
const formulaLabel = isISOMode ? 'R = S × F × P × A' : 'R = S × E × P'
return (
<div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6">
@@ -164,42 +275,120 @@ function HazardForm({
/>
</div>
{/* S/E/P Sliders */}
{/* Lifecycle Phase */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Lebensphase</label>
<select
value={formData.lifecycle_phase}
onChange={(e) => setFormData({ ...formData, lifecycle_phase: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="">-- Keine Auswahl --</option>
{lifecyclePhases.map((p) => (
<option key={p.id} value={p.id}>{p.label_de}</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Betroffene Personen</label>
<select
value={formData.affected_person}
onChange={(e) => setFormData({ ...formData, affected_person: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="">-- Bitte waehlen --</option>
{roles.map((r) => (
<option key={r.id} value={r.id}>{r.label_de}</option>
))}
</select>
</div>
</div>
{/* Extended fields toggle */}
<button
type="button"
onClick={() => setShowExtended(!showExtended)}
className="text-sm text-purple-600 hover:text-purple-700 font-medium"
>
{showExtended ? 'Weniger Felder anzeigen' : 'Weitere Felder anzeigen (Ausloeser, Gefahrenzone, Modul...)'}
</button>
{showExtended && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 p-4 bg-gray-50 dark:bg-gray-750 rounded-lg">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Ausloeseereignis</label>
<input
type="text"
value={formData.trigger_event}
onChange={(e) => setFormData({ ...formData, trigger_event: e.target.value })}
placeholder="z.B. Schutztuer offen bei Betrieb"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Moeglicher Schaden</label>
<input
type="text"
value={formData.possible_harm}
onChange={(e) => setFormData({ ...formData, possible_harm: e.target.value })}
placeholder="z.B. Schwere Quetschverletzung"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Gefahrenzone</label>
<input
type="text"
value={formData.hazardous_zone}
onChange={(e) => setFormData({ ...formData, hazardous_zone: e.target.value })}
placeholder="z.B. Roboter-Arbeitsbereich"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Maschinenmodul</label>
<input
type="text"
value={formData.machine_module}
onChange={(e) => setFormData({ ...formData, machine_module: e.target.value })}
placeholder="z.B. Antriebseinheit"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
/>
</div>
</div>
)}
{/* S/F/P/A Sliders */}
<div className="bg-gray-50 dark:bg-gray-750 rounded-lg p-4">
<h4 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">Risikobewertung (S x E x P)</h4>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<h4 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">
Risikobewertung ({formulaLabel})
</h4>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div>
<label className="block text-sm text-gray-600 dark:text-gray-400 mb-1">
Schwere (S): <span className="font-bold">{formData.severity}</span>
</label>
<input
type="range"
min={1}
max={5}
value={formData.severity}
type="range" min={1} max={5} value={formData.severity}
onChange={(e) => setFormData({ ...formData, severity: Number(e.target.value) })}
className="w-full accent-purple-600"
/>
<div className="flex justify-between text-xs text-gray-400">
<span>Gering</span>
<span>Toedlich</span>
<span>Gering</span><span>Toedlich</span>
</div>
</div>
<div>
<label className="block text-sm text-gray-600 dark:text-gray-400 mb-1">
Exposition (E): <span className="font-bold">{formData.exposure}</span>
Haeufigkeit (F): <span className="font-bold">{formData.exposure}</span>
</label>
<input
type="range"
min={1}
max={5}
value={formData.exposure}
type="range" min={1} max={5} value={formData.exposure}
onChange={(e) => setFormData({ ...formData, exposure: Number(e.target.value) })}
className="w-full accent-purple-600"
/>
<div className="flex justify-between text-xs text-gray-400">
<span>Selten</span>
<span>Staendig</span>
<span>Selten</span><span>Staendig</span>
</div>
</div>
<div>
@@ -207,23 +396,32 @@ function HazardForm({
Wahrscheinlichkeit (P): <span className="font-bold">{formData.probability}</span>
</label>
<input
type="range"
min={1}
max={5}
value={formData.probability}
type="range" min={1} max={5} value={formData.probability}
onChange={(e) => setFormData({ ...formData, probability: Number(e.target.value) })}
className="w-full accent-purple-600"
/>
<div className="flex justify-between text-xs text-gray-400">
<span>Unwahrscheinlich</span>
<span>Sehr wahrscheinlich</span>
<span>Unwahrscheinlich</span><span>Sehr wahrscheinlich</span>
</div>
</div>
<div>
<label className="block text-sm text-gray-600 dark:text-gray-400 mb-1">
Vermeidbarkeit (A): <span className="font-bold">{formData.avoidance}</span>
</label>
<input
type="range" min={1} max={5} value={formData.avoidance}
onChange={(e) => setFormData({ ...formData, avoidance: Number(e.target.value) })}
className="w-full accent-purple-600"
/>
<div className="flex justify-between text-xs text-gray-400">
<span>Leicht</span><span>Unmoeglich</span>
</div>
</div>
</div>
<div className={`mt-4 p-3 rounded-lg border ${getRiskColor(riskLevel)}`}>
<div className="flex items-center justify-between">
<span className="text-sm font-medium">R_inherent = S x E x P</span>
<span className="text-sm font-medium">{formulaLabel}</span>
<div className="flex items-center gap-2">
<span className="text-lg font-bold">{rInherent}</span>
<RiskBadge level={riskLevel} />
@@ -264,6 +462,7 @@ function LibraryModal({
}) {
const [search, setSearch] = useState('')
const [filterCat, setFilterCat] = useState('')
const [expandedId, setExpandedId] = useState<string | null>(null)
const filtered = library.filter((h) => {
const matchSearch = !search || h.name.toLowerCase().includes(search.toLowerCase()) || h.description.toLowerCase().includes(search.toLowerCase())
@@ -273,10 +472,10 @@ function LibraryModal({
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white dark:bg-gray-800 rounded-xl w-full max-w-2xl max-h-[80vh] flex flex-col">
<div className="bg-white dark:bg-gray-800 rounded-xl w-full max-w-3xl max-h-[85vh] flex flex-col">
<div className="p-6 border-b border-gray-200 dark:border-gray-700">
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">Gefaehrdungsbibliothek</h3>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">Gefaehrdungsbibliothek ({filtered.length} Eintraege)</h3>
<button onClick={onClose} className="p-1 text-gray-400 hover:text-gray-600 rounded">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
@@ -306,24 +505,62 @@ function LibraryModal({
<div className="flex-1 overflow-auto p-4 space-y-2">
{filtered.length > 0 ? (
filtered.map((item) => (
<div
key={item.id}
className="flex items-center justify-between p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-750"
>
<div className="flex-1 min-w-0 mr-3">
<div className="text-sm font-medium text-gray-900 dark:text-white">{item.name}</div>
<div className="text-xs text-gray-500 truncate">{item.description}</div>
<div className="flex items-center gap-2 mt-1">
<span className="text-xs text-gray-400">{CATEGORY_LABELS[item.category] || item.category}</span>
<span className="text-xs text-gray-400">S:{item.default_severity} E:{item.default_exposure} P:{item.default_probability}</span>
<div key={item.id} className="rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-750">
<div className="flex items-center justify-between p-3">
<div
className="flex-1 min-w-0 mr-3 cursor-pointer"
onClick={() => setExpandedId(expandedId === item.id ? null : item.id)}
>
<div className="text-sm font-medium text-gray-900 dark:text-white">{item.name}</div>
<div className="text-xs text-gray-500 truncate">{item.description}</div>
<div className="flex items-center gap-2 mt-1">
<span className="text-xs text-gray-400">{CATEGORY_LABELS[item.category] || item.category}</span>
<span className="text-xs text-gray-400">
S:{item.default_severity} F:{item.default_exposure || 3} P:{item.default_probability} A:{item.default_avoidance || 3}
</span>
</div>
</div>
<button
onClick={() => onAdd(item)}
className="flex-shrink-0 px-3 py-1.5 text-xs bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
>
Hinzufuegen
</button>
</div>
<button
onClick={() => onAdd(item)}
className="flex-shrink-0 px-3 py-1.5 text-xs bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
>
Hinzufuegen
</button>
{expandedId === item.id && (
<div className="px-3 pb-3 space-y-2 text-xs">
{item.typical_causes && item.typical_causes.length > 0 && (
<div>
<span className="font-medium text-gray-600">Typische Ursachen: </span>
<span className="text-gray-500">{item.typical_causes.join(', ')}</span>
</div>
)}
{item.typical_harm && (
<div>
<span className="font-medium text-gray-600">Typischer Schaden: </span>
<span className="text-gray-500">{item.typical_harm}</span>
</div>
)}
{item.recommended_measures_design && item.recommended_measures_design.length > 0 && (
<div>
<span className="font-medium text-blue-600">Konstruktiv: </span>
<span className="text-gray-500">{item.recommended_measures_design.join(', ')}</span>
</div>
)}
{item.recommended_measures_technical && item.recommended_measures_technical.length > 0 && (
<div>
<span className="font-medium text-green-600">Technisch: </span>
<span className="text-gray-500">{item.recommended_measures_technical.join(', ')}</span>
</div>
)}
{item.recommended_measures_information && item.recommended_measures_information.length > 0 && (
<div>
<span className="font-medium text-yellow-600">Information: </span>
<span className="text-gray-500">{item.recommended_measures_information.join(', ')}</span>
</div>
)}
</div>
)}
</div>
))
) : (
@@ -340,6 +577,8 @@ export default function HazardsPage() {
const projectId = params.projectId as string
const [hazards, setHazards] = useState<Hazard[]>([])
const [library, setLibrary] = useState<LibraryHazard[]>([])
const [lifecyclePhases, setLifecyclePhases] = useState<LifecyclePhase[]>([])
const [roles, setRoles] = useState<RoleInfo[]>([])
const [loading, setLoading] = useState(true)
const [showForm, setShowForm] = useState(false)
const [showLibrary, setShowLibrary] = useState(false)
@@ -347,6 +586,8 @@ export default function HazardsPage() {
useEffect(() => {
fetchHazards()
fetchLifecyclePhases()
fetchRoles()
}, [projectId])
async function fetchHazards() {
@@ -363,12 +604,36 @@ export default function HazardsPage() {
}
}
async function fetchLifecyclePhases() {
try {
const res = await fetch('/api/sdk/v1/iace/lifecycle-phases')
if (res.ok) {
const json = await res.json()
setLifecyclePhases(json.lifecycle_phases || [])
}
} catch (err) {
console.error('Failed to fetch lifecycle phases:', err)
}
}
async function fetchRoles() {
try {
const res = await fetch('/api/sdk/v1/iace/roles')
if (res.ok) {
const json = await res.json()
setRoles(json.roles || [])
}
} catch (err) {
console.error('Failed to fetch roles:', err)
}
}
async function fetchLibrary() {
try {
const res = await fetch('/api/sdk/v1/iace/hazard-library')
if (res.ok) {
const json = await res.json()
setLibrary(json.hazards || json || [])
setLibrary(json.hazard_library || json.hazards || json || [])
}
} catch (err) {
console.error('Failed to fetch hazard library:', err)
@@ -385,9 +650,11 @@ export default function HazardsPage() {
name: item.name,
description: item.description,
category: item.category,
sub_category: item.sub_category || '',
severity: item.default_severity,
exposure: item.default_exposure,
exposure: item.default_exposure || 3,
probability: item.default_probability,
avoidance: item.default_avoidance || 3,
}),
})
if (res.ok) {
@@ -458,7 +725,7 @@ export default function HazardsPage() {
<div>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Hazard Log</h1>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
Gefaehrdungsanalyse mit Risikobewertung nach S x E x P Methode.
Gefaehrdungsanalyse mit 4-Faktor-Risikobewertung (S x F x P x A).
</p>
</div>
<div className="flex items-center gap-2">
@@ -499,14 +766,18 @@ export default function HazardsPage() {
{/* Stats */}
{hazards.length > 0 && (
<div className="grid grid-cols-2 md:grid-cols-5 gap-3">
<div className="grid grid-cols-2 md:grid-cols-7 gap-3">
<div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4 text-center">
<div className="text-2xl font-bold text-gray-900 dark:text-white">{hazards.length}</div>
<div className="text-xs text-gray-500">Gesamt</div>
</div>
<div className="bg-white dark:bg-gray-800 rounded-lg border border-red-300 p-4 text-center">
<div className="text-2xl font-bold text-red-800">{hazards.filter((h) => h.risk_level === 'not_acceptable').length}</div>
<div className="text-xs text-red-800">Nicht akzeptabel</div>
</div>
<div className="bg-white dark:bg-gray-800 rounded-lg border border-red-200 p-4 text-center">
<div className="text-2xl font-bold text-red-600">{hazards.filter((h) => h.risk_level === 'critical').length}</div>
<div className="text-xs text-red-600">Kritisch</div>
<div className="text-2xl font-bold text-red-600">{hazards.filter((h) => h.risk_level === 'very_high' || h.risk_level === 'critical').length}</div>
<div className="text-xs text-red-600">Sehr hoch/Kritisch</div>
</div>
<div className="bg-white dark:bg-gray-800 rounded-lg border border-orange-200 p-4 text-center">
<div className="text-2xl font-bold text-orange-600">{hazards.filter((h) => h.risk_level === 'high').length}</div>
@@ -520,12 +791,21 @@ export default function HazardsPage() {
<div className="text-2xl font-bold text-green-600">{hazards.filter((h) => h.risk_level === 'low').length}</div>
<div className="text-xs text-green-600">Niedrig</div>
</div>
<div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 p-4 text-center">
<div className="text-2xl font-bold text-gray-500">{hazards.filter((h) => h.risk_level === 'negligible').length}</div>
<div className="text-xs text-gray-500">Vernachlaessigbar</div>
</div>
</div>
)}
{/* Form */}
{showForm && (
<HazardForm onSubmit={handleSubmit} onCancel={() => setShowForm(false)} />
<HazardForm
onSubmit={handleSubmit}
onCancel={() => setShowForm(false)}
lifecyclePhases={lifecyclePhases}
roles={roles}
/>
)}
{/* Library Modal */}
@@ -546,19 +826,20 @@ export default function HazardsPage() {
<tr className="bg-gray-50 dark:bg-gray-750 border-b border-gray-200 dark:border-gray-700">
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Bezeichnung</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Kategorie</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Komponente</th>
<th className="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">S</th>
<th className="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">E</th>
<th className="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">F</th>
<th className="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">P</th>
<th className="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">A</th>
<th className="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">R</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Risiko</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Review</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th className="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Aktionen</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200 dark:divide-gray-700">
{hazards
.sort((a, b) => b.r_inherent - a.r_inherent)
.sort((a, b) => (b.r_inherent || 0) - (a.r_inherent || 0))
.map((hazard) => (
<tr key={hazard.id} className="hover:bg-gray-50 dark:hover:bg-gray-750 transition-colors">
<td className="px-4 py-3">
@@ -566,14 +847,20 @@ export default function HazardsPage() {
{hazard.description && (
<div className="text-xs text-gray-500 truncate max-w-[250px]">{hazard.description}</div>
)}
{hazard.lifecycle_phase && (
<div className="text-xs text-purple-500 mt-0.5">
{lifecyclePhases.find(p => p.id === hazard.lifecycle_phase)?.label_de || hazard.lifecycle_phase}
</div>
)}
</td>
<td className="px-4 py-3 text-sm text-gray-600">{CATEGORY_LABELS[hazard.category] || hazard.category}</td>
<td className="px-4 py-3 text-sm text-gray-600">{hazard.component_name || '--'}</td>
<td className="px-4 py-3 text-sm text-gray-900 dark:text-white text-center font-medium">{hazard.severity}</td>
<td className="px-4 py-3 text-sm text-gray-900 dark:text-white text-center font-medium">{hazard.exposure}</td>
<td className="px-4 py-3 text-sm text-gray-900 dark:text-white text-center font-medium">{hazard.probability}</td>
<td className="px-4 py-3 text-sm text-gray-900 dark:text-white text-center font-medium">{hazard.avoidance || '-'}</td>
<td className="px-4 py-3 text-sm text-gray-900 dark:text-white text-center font-bold">{hazard.r_inherent}</td>
<td className="px-4 py-3"><RiskBadge level={hazard.risk_level} /></td>
<td className="px-4 py-3"><ReviewStatusBadge status={hazard.review_status || 'draft'} /></td>
<td className="px-4 py-3">
<span className="text-xs text-gray-500">{STATUS_LABELS[hazard.status] || hazard.status}</span>
</td>

View File

@@ -20,14 +20,33 @@ interface Hazard {
id: string
name: string
risk_level: string
category?: string
}
interface ProtectiveMeasure {
id: string
reduction_type: string
sub_type: string
name: string
description: string
hazard_category: string
examples: string[]
}
const REDUCTION_TYPES = {
design: {
label: 'Design',
label: 'Stufe 1: Design',
description: 'Inhaerent sichere Konstruktion',
color: 'border-blue-200 bg-blue-50',
headerColor: 'bg-blue-100 text-blue-800',
subTypes: [
{ value: 'geometry', label: 'Geometrie & Anordnung' },
{ value: 'force_energy', label: 'Kraft & Energie' },
{ value: 'material', label: 'Material & Stabilitaet' },
{ value: 'ergonomics', label: 'Ergonomie' },
{ value: 'control_design', label: 'Steuerungstechnik' },
{ value: 'fluid_design', label: 'Pneumatik / Hydraulik' },
],
icon: (
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z" />
@@ -35,10 +54,21 @@ const REDUCTION_TYPES = {
),
},
protection: {
label: 'Schutz',
label: 'Stufe 2: Schutz',
description: 'Technische Schutzmassnahmen',
color: 'border-green-200 bg-green-50',
headerColor: 'bg-green-100 text-green-800',
subTypes: [
{ value: 'fixed_guard', label: 'Feststehende Schutzeinrichtung' },
{ value: 'movable_guard', label: 'Bewegliche Schutzeinrichtung' },
{ value: 'electro_sensitive', label: 'Optoelektronisch' },
{ value: 'pressure_sensitive', label: 'Druckempfindlich' },
{ value: 'emergency_stop', label: 'Not-Halt' },
{ value: 'electrical_protection', label: 'Elektrischer Schutz' },
{ value: 'thermal_protection', label: 'Thermischer Schutz' },
{ value: 'fluid_protection', label: 'Hydraulik/Pneumatik-Schutz' },
{ value: 'extraction', label: 'Absaugung / Kapselung' },
],
icon: (
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
@@ -46,10 +76,18 @@ const REDUCTION_TYPES = {
),
},
information: {
label: 'Information',
label: 'Stufe 3: Information',
description: 'Hinweise und Schulungen',
color: 'border-yellow-200 bg-yellow-50',
headerColor: 'bg-yellow-100 text-yellow-800',
subTypes: [
{ value: 'signage', label: 'Beschilderung & Kennzeichnung' },
{ value: 'manual', label: 'Betriebsanleitung' },
{ value: 'training', label: 'Schulung & Unterweisung' },
{ value: 'ppe', label: 'PSA (Schutzausruestung)' },
{ value: 'organizational', label: 'Organisatorisch' },
{ value: 'marking', label: 'Markierung & Codierung' },
],
icon: (
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
@@ -76,6 +114,132 @@ function StatusBadge({ status }: { status: string }) {
)
}
function HierarchyWarning({ onDismiss }: { onDismiss: () => void }) {
return (
<div className="bg-amber-50 border border-amber-300 rounded-xl p-4 flex items-start gap-3">
<svg className="w-6 h-6 text-amber-600 flex-shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<div className="flex-1">
<h4 className="text-sm font-semibold text-amber-800">Hierarchie-Warnung: Massnahmen vom Typ &quot;Information&quot;</h4>
<p className="text-sm text-amber-700 mt-1">
Hinweismassnahmen (Stufe 3) duerfen <strong>nicht als Primaermassnahme</strong> akzeptiert werden, wenn konstruktive
(Stufe 1) oder technische (Stufe 2) Massnahmen moeglich und zumutbar sind. Pruefen Sie, ob hoeherwertige
Massnahmen ergaenzt werden koennen.
</p>
</div>
<button onClick={onDismiss} className="text-amber-400 hover:text-amber-600 transition-colors">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
)
}
function MeasuresLibraryModal({
measures,
onSelect,
onClose,
filterType,
}: {
measures: ProtectiveMeasure[]
onSelect: (measure: ProtectiveMeasure) => void
onClose: () => void
filterType?: string
}) {
const [search, setSearch] = useState('')
const [selectedSubType, setSelectedSubType] = useState('')
const filtered = measures.filter((m) => {
if (filterType && m.reduction_type !== filterType) return false
if (selectedSubType && m.sub_type !== selectedSubType) return false
if (search) {
const q = search.toLowerCase()
return m.name.toLowerCase().includes(q) || m.description.toLowerCase().includes(q)
}
return true
})
const subTypes = [...new Set(measures.filter((m) => !filterType || m.reduction_type === filterType).map((m) => m.sub_type))].filter(Boolean)
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white dark:bg-gray-800 rounded-xl w-full max-w-3xl max-h-[80vh] flex flex-col">
<div className="p-6 border-b border-gray-200 dark:border-gray-700">
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">Massnahmen-Bibliothek</h3>
<button onClick={onClose} className="p-1 text-gray-400 hover:text-gray-600 rounded transition-colors">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div className="flex gap-3">
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Massnahme suchen..."
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
/>
{subTypes.length > 1 && (
<select
value={selectedSubType}
onChange={(e) => setSelectedSubType(e.target.value)}
className="px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white text-sm"
>
<option value="">Alle Sub-Typen</option>
{subTypes.map((st) => (
<option key={st} value={st}>{st}</option>
))}
</select>
)}
</div>
<div className="mt-2 text-xs text-gray-500">{filtered.length} Massnahmen</div>
</div>
<div className="flex-1 overflow-y-auto p-6 space-y-3">
{filtered.map((m) => (
<div
key={m.id}
className="border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:border-purple-300 hover:bg-purple-50/30 transition-colors cursor-pointer"
onClick={() => onSelect(m)}
>
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<span className="text-xs font-mono text-gray-400">{m.id}</span>
{m.sub_type && (
<span className="text-xs px-1.5 py-0.5 rounded bg-gray-100 text-gray-600">{m.sub_type}</span>
)}
</div>
<h4 className="text-sm font-medium text-gray-900 dark:text-white">{m.name}</h4>
<p className="text-xs text-gray-500 mt-1">{m.description}</p>
{m.examples && m.examples.length > 0 && (
<div className="mt-2 flex flex-wrap gap-1">
{m.examples.map((ex, i) => (
<span key={i} className="text-xs px-1.5 py-0.5 rounded bg-purple-50 text-purple-600">
{ex}
</span>
))}
</div>
)}
</div>
<button className="ml-3 px-3 py-1.5 text-xs bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors flex-shrink-0">
Uebernehmen
</button>
</div>
</div>
))}
{filtered.length === 0 && (
<div className="text-center py-8 text-gray-500">Keine Massnahmen gefunden</div>
)}
</div>
</div>
</div>
)
}
interface MitigationFormData {
title: string
description: string
@@ -88,11 +252,13 @@ function MitigationForm({
onCancel,
hazards,
preselectedType,
onOpenLibrary,
}: {
onSubmit: (data: MitigationFormData) => void
onCancel: () => void
hazards: Hazard[]
preselectedType?: 'design' | 'protection' | 'information'
onOpenLibrary: (type?: string) => void
}) {
const [formData, setFormData] = useState<MitigationFormData>({
title: '',
@@ -112,7 +278,15 @@ function MitigationForm({
return (
<div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">Neue Massnahme</h3>
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">Neue Massnahme</h3>
<button
onClick={() => onOpenLibrary(formData.reduction_type)}
className="text-sm px-3 py-1.5 bg-purple-50 text-purple-700 border border-purple-200 rounded-lg hover:bg-purple-100 transition-colors"
>
Aus Bibliothek waehlen
</button>
</div>
<div className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
@@ -132,9 +306,9 @@ function MitigationForm({
onChange={(e) => setFormData({ ...formData, reduction_type: e.target.value as MitigationFormData['reduction_type'] })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="design">Design - Inhaerent sichere Konstruktion</option>
<option value="protection">Schutz - Technische Schutzmassnahmen</option>
<option value="information">Information - Hinweise und Schulungen</option>
<option value="design">Stufe 1: Design - Inhaerent sichere Konstruktion</option>
<option value="protection">Stufe 2: Schutz - Technische Schutzmassnahmen</option>
<option value="information">Stufe 3: Information - Hinweise und Schulungen</option>
</select>
</div>
</div>
@@ -246,6 +420,10 @@ export default function MitigationsPage() {
const [loading, setLoading] = useState(true)
const [showForm, setShowForm] = useState(false)
const [preselectedType, setPreselectedType] = useState<'design' | 'protection' | 'information' | undefined>()
const [hierarchyWarning, setHierarchyWarning] = useState<boolean>(false)
const [showLibrary, setShowLibrary] = useState(false)
const [libraryFilter, setLibraryFilter] = useState<string | undefined>()
const [measures, setMeasures] = useState<ProtectiveMeasure[]>([])
useEffect(() => {
fetchData()
@@ -259,11 +437,14 @@ export default function MitigationsPage() {
])
if (mitRes.ok) {
const json = await mitRes.json()
setMitigations(json.mitigations || json || [])
const mits = json.mitigations || json || []
setMitigations(mits)
// Check hierarchy: if information-only measures exist without design/protection
validateHierarchy(mits)
}
if (hazRes.ok) {
const json = await hazRes.json()
setHazards((json.hazards || json || []).map((h: Hazard) => ({ id: h.id, name: h.name, risk_level: h.risk_level })))
setHazards((json.hazards || json || []).map((h: Hazard) => ({ id: h.id, name: h.name, risk_level: h.risk_level, category: h.category })))
}
} catch (err) {
console.error('Failed to fetch data:', err)
@@ -272,6 +453,56 @@ export default function MitigationsPage() {
}
}
async function validateHierarchy(mits: Mitigation[]) {
if (mits.length === 0) return
try {
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/validate-mitigation-hierarchy`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
mitigations: mits.map((m) => ({
reduction_type: m.reduction_type,
linked_hazard_ids: m.linked_hazard_ids,
})),
}),
})
if (res.ok) {
const json = await res.json()
setHierarchyWarning(json.has_warning === true)
}
} catch {
// Non-critical, ignore
}
}
async function fetchMeasuresLibrary(type?: string) {
try {
const url = type
? `/api/sdk/v1/iace/protective-measures-library?reduction_type=${type}`
: '/api/sdk/v1/iace/protective-measures-library'
const res = await fetch(url)
if (res.ok) {
const json = await res.json()
setMeasures(json.protective_measures || [])
}
} catch (err) {
console.error('Failed to fetch measures library:', err)
}
}
function handleOpenLibrary(type?: string) {
setLibraryFilter(type)
fetchMeasuresLibrary(type)
setShowLibrary(true)
}
function handleSelectMeasure(measure: ProtectiveMeasure) {
setShowLibrary(false)
setShowForm(true)
setPreselectedType(measure.reduction_type as 'design' | 'protection' | 'information')
// The form will be pre-filled with the type; user can edit title/description
}
async function handleSubmit(data: MitigationFormData) {
try {
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/mitigations`, {
@@ -341,23 +572,39 @@ export default function MitigationsPage() {
<div>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Massnahmen</h1>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
Risikominderung nach dem 3-Stufen-Verfahren: Design, Schutz, Information.
Risikominderung nach dem 3-Stufen-Verfahren: Design &rarr; Schutz &rarr; Information.
</p>
</div>
<button
onClick={() => {
setPreselectedType(undefined)
setShowForm(true)
}}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Massnahme hinzufuegen
</button>
<div className="flex items-center gap-3">
<button
onClick={() => handleOpenLibrary()}
className="flex items-center gap-2 px-4 py-2 bg-white border border-purple-300 text-purple-700 rounded-lg hover:bg-purple-50 transition-colors"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
Bibliothek
</button>
<button
onClick={() => {
setPreselectedType(undefined)
setShowForm(true)
}}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Massnahme hinzufuegen
</button>
</div>
</div>
{/* Hierarchy Warning */}
{hierarchyWarning && (
<HierarchyWarning onDismiss={() => setHierarchyWarning(false)} />
)}
{/* Form */}
{showForm && (
<MitigationForm
@@ -368,6 +615,17 @@ export default function MitigationsPage() {
}}
hazards={hazards}
preselectedType={preselectedType}
onOpenLibrary={handleOpenLibrary}
/>
)}
{/* Measures Library Modal */}
{showLibrary && (
<MeasuresLibraryModal
measures={measures}
onSelect={handleSelectMeasure}
onClose={() => setShowLibrary(false)}
filterType={libraryFilter}
/>
)}
@@ -378,7 +636,7 @@ export default function MitigationsPage() {
const items = byType[type]
return (
<div key={type} className={`rounded-xl border ${config.color} p-4`}>
<div className={`flex items-center gap-2 px-3 py-2 rounded-lg ${config.headerColor} mb-4`}>
<div className={`flex items-center gap-2 px-3 py-2 rounded-lg ${config.headerColor} mb-3`}>
{config.icon}
<div>
<h3 className="text-sm font-semibold">{config.label}</h3>
@@ -387,6 +645,15 @@ export default function MitigationsPage() {
<span className="ml-auto text-sm font-bold">{items.length}</span>
</div>
{/* Sub-types overview */}
<div className="mb-3 flex flex-wrap gap-1">
{config.subTypes.map((st) => (
<span key={st.value} className="text-xs px-1.5 py-0.5 rounded bg-white/60 text-gray-500 border border-gray-200/50">
{st.label}
</span>
))}
</div>
<div className="space-y-3">
{items.map((m) => (
<MitigationCard
@@ -398,12 +665,23 @@ export default function MitigationsPage() {
))}
</div>
<button
onClick={() => handleAddForType(type)}
className="mt-3 w-full py-2 text-sm text-gray-500 hover:text-purple-600 hover:bg-white rounded-lg border border-dashed border-gray-300 hover:border-purple-300 transition-colors"
>
+ Massnahme hinzufuegen
</button>
<div className="mt-3 flex gap-2">
<button
onClick={() => handleAddForType(type)}
className="flex-1 py-2 text-sm text-gray-500 hover:text-purple-600 hover:bg-white rounded-lg border border-dashed border-gray-300 hover:border-purple-300 transition-colors"
>
+ Hinzufuegen
</button>
<button
onClick={() => handleOpenLibrary(type)}
className="py-2 px-3 text-sm text-gray-400 hover:text-purple-600 hover:bg-white rounded-lg border border-dashed border-gray-300 hover:border-purple-300 transition-colors"
title="Aus Bibliothek waehlen"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
</button>
</div>
</div>
)
})}

View File

@@ -20,13 +20,16 @@ interface VerificationItem {
}
const VERIFICATION_METHODS = [
{ value: 'test', label: 'Test' },
{ value: 'analysis', label: 'Analyse' },
{ value: 'inspection', label: 'Inspektion' },
{ value: 'simulation', label: 'Simulation' },
{ value: 'review', label: 'Review' },
{ value: 'demonstration', label: 'Demonstration' },
{ value: 'certification', label: 'Zertifizierung' },
{ value: 'design_review', label: 'Design-Review', description: 'Systematische Pruefung der Konstruktionsunterlagen' },
{ value: 'calculation', label: 'Berechnung', description: 'Rechnerischer Nachweis (FEM, Festigkeit, Thermik)' },
{ value: 'test_report', label: 'Pruefbericht', description: 'Dokumentierter Test mit Messprotokoll' },
{ value: 'validation', label: 'Validierung', description: 'Nachweis der Eignung unter realen Betriebsbedingungen' },
{ value: 'electrical_test', label: 'Elektrische Pruefung', description: 'Isolationsmessung, Schutzleiter, Spannungsfestigkeit' },
{ value: 'software_test', label: 'Software-Test', description: 'Unit-, Integrations- oder Systemtest der Steuerungssoftware' },
{ value: 'penetration_test', label: 'Penetrationstest', description: 'Security-Test der Netzwerk- und Steuerungskomponenten' },
{ value: 'acceptance_protocol', label: 'Abnahmeprotokoll', description: 'Formelle Abnahme mit Checkliste und Unterschrift' },
{ value: 'user_test', label: 'Anwendertest', description: 'Pruefung durch Bediener unter realen Einsatzbedingungen' },
{ value: 'documentation_release', label: 'Dokumentenfreigabe', description: 'Formelle Freigabe der technischen Dokumentation' },
]
const STATUS_CONFIG: Record<string, { label: string; color: string }> = {

View File

@@ -524,6 +524,11 @@ func main() {
iaceRoutes.GET("/hazard-library", iaceHandler.ListHazardLibrary)
// Controls Library (project-independent)
iaceRoutes.GET("/controls-library", iaceHandler.ListControlsLibrary)
// ISO 12100 reference data (project-independent)
iaceRoutes.GET("/lifecycle-phases", iaceHandler.ListLifecyclePhases)
iaceRoutes.GET("/roles", iaceHandler.ListRoles)
iaceRoutes.GET("/evidence-types", iaceHandler.ListEvidenceTypes)
iaceRoutes.GET("/protective-measures-library", iaceHandler.ListProtectiveMeasures)
// Project Management
iaceRoutes.POST("/projects", iaceHandler.CreateProject)
@@ -562,6 +567,7 @@ func main() {
iaceRoutes.POST("/projects/:id/hazards/:hid/mitigations", iaceHandler.CreateMitigation)
iaceRoutes.PUT("/mitigations/:mid", iaceHandler.UpdateMitigation)
iaceRoutes.POST("/mitigations/:mid/verify", iaceHandler.VerifyMitigation)
iaceRoutes.POST("/projects/:id/validate-mitigation-hierarchy", iaceHandler.ValidateMitigationHierarchy)
// Evidence
iaceRoutes.POST("/projects/:id/evidence", iaceHandler.UploadEvidence)

View File

@@ -917,7 +917,14 @@ func (h *IACEHandler) AssessRisk(c *gin.Context) {
inherentRisk := h.engine.CalculateInherentRisk(req.Severity, req.Exposure, req.Probability, req.Avoidance)
controlEff := h.engine.CalculateControlEffectiveness(req.ControlMaturity, req.ControlCoverage, req.TestEvidenceStrength)
residualRisk := h.engine.CalculateResidualRisk(req.Severity, req.Exposure, req.Probability, controlEff)
riskLevel := h.engine.DetermineRiskLevel(residualRisk)
// ISO 12100 mode: use ISO thresholds when avoidance is set
var riskLevel iace.RiskLevel
if req.Avoidance >= 1 {
riskLevel = h.engine.DetermineRiskLevelISO(inherentRisk)
} else {
riskLevel = h.engine.DetermineRiskLevel(residualRisk)
}
acceptable, acceptanceReason := h.engine.IsAcceptable(residualRisk, false, req.AcceptanceJustification != "")
// Determine version by checking existing assessments
@@ -1862,3 +1869,186 @@ func sortStrings(s []string) {
}
}
}
// ============================================================================
// ISO 12100 Endpoints
// ============================================================================
// ListLifecyclePhases handles GET /lifecycle-phases
// Returns the 12 machine lifecycle phases with DE/EN labels.
func (h *IACEHandler) ListLifecyclePhases(c *gin.Context) {
phases, err := h.store.ListLifecyclePhases(c.Request.Context())
if err != nil {
// Fallback: return hardcoded 25 phases if DB table not yet migrated
phases = []iace.LifecyclePhaseInfo{
{ID: "transport", LabelDE: "Transport", LabelEN: "Transport", Sort: 1},
{ID: "storage", LabelDE: "Lagerung", LabelEN: "Storage", Sort: 2},
{ID: "assembly", LabelDE: "Montage", LabelEN: "Assembly", Sort: 3},
{ID: "installation", LabelDE: "Installation", LabelEN: "Installation", Sort: 4},
{ID: "commissioning", LabelDE: "Inbetriebnahme", LabelEN: "Commissioning", Sort: 5},
{ID: "parameterization", LabelDE: "Parametrierung", LabelEN: "Parameterization", Sort: 6},
{ID: "setup", LabelDE: "Einrichten / Setup", LabelEN: "Setup", Sort: 7},
{ID: "normal_operation", LabelDE: "Normalbetrieb", LabelEN: "Normal Operation", Sort: 8},
{ID: "automatic_operation", LabelDE: "Automatikbetrieb", LabelEN: "Automatic Operation", Sort: 9},
{ID: "manual_operation", LabelDE: "Handbetrieb", LabelEN: "Manual Operation", Sort: 10},
{ID: "teach_mode", LabelDE: "Teach-Modus", LabelEN: "Teach Mode", Sort: 11},
{ID: "production_start", LabelDE: "Produktionsstart", LabelEN: "Production Start", Sort: 12},
{ID: "production_stop", LabelDE: "Produktionsstopp", LabelEN: "Production Stop", Sort: 13},
{ID: "process_monitoring", LabelDE: "Prozessueberwachung", LabelEN: "Process Monitoring", Sort: 14},
{ID: "cleaning", LabelDE: "Reinigung", LabelEN: "Cleaning", Sort: 15},
{ID: "maintenance", LabelDE: "Wartung", LabelEN: "Maintenance", Sort: 16},
{ID: "inspection", LabelDE: "Inspektion", LabelEN: "Inspection", Sort: 17},
{ID: "calibration", LabelDE: "Kalibrierung", LabelEN: "Calibration", Sort: 18},
{ID: "fault_clearing", LabelDE: "Stoerungsbeseitigung", LabelEN: "Fault Clearing", Sort: 19},
{ID: "repair", LabelDE: "Reparatur", LabelEN: "Repair", Sort: 20},
{ID: "changeover", LabelDE: "Umruestung", LabelEN: "Changeover", Sort: 21},
{ID: "software_update", LabelDE: "Software-Update", LabelEN: "Software Update", Sort: 22},
{ID: "remote_maintenance", LabelDE: "Fernwartung", LabelEN: "Remote Maintenance", Sort: 23},
{ID: "decommissioning", LabelDE: "Ausserbetriebnahme", LabelEN: "Decommissioning", Sort: 24},
{ID: "disposal", LabelDE: "Demontage / Entsorgung", LabelEN: "Dismantling / Disposal", Sort: 25},
}
}
if phases == nil {
phases = []iace.LifecyclePhaseInfo{}
}
c.JSON(http.StatusOK, gin.H{
"lifecycle_phases": phases,
"total": len(phases),
})
}
// ListProtectiveMeasures handles GET /protective-measures-library
// Returns the protective measures library, optionally filtered by ?reduction_type and ?hazard_category.
func (h *IACEHandler) ListProtectiveMeasures(c *gin.Context) {
reductionType := c.Query("reduction_type")
hazardCategory := c.Query("hazard_category")
all := iace.GetProtectiveMeasureLibrary()
var filtered []iace.ProtectiveMeasureEntry
for _, entry := range all {
if reductionType != "" && entry.ReductionType != reductionType {
continue
}
if hazardCategory != "" && entry.HazardCategory != hazardCategory && entry.HazardCategory != "general" && entry.HazardCategory != "" {
continue
}
filtered = append(filtered, entry)
}
if filtered == nil {
filtered = []iace.ProtectiveMeasureEntry{}
}
c.JSON(http.StatusOK, gin.H{
"protective_measures": 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) {
projectID, err := uuid.Parse(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
return
}
var req iace.ValidateMitigationHierarchyRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Get existing mitigations for the hazard
mitigations, err := h.store.ListMitigations(c.Request.Context(), req.HazardID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
_ = projectID // projectID used for authorization context
warnings := h.engine.ValidateProtectiveMeasureHierarchy(req.ReductionType, mitigations)
c.JSON(http.StatusOK, iace.ValidateMitigationHierarchyResponse{
Valid: len(warnings) == 0,
Warnings: warnings,
})
}
// ListRoles handles GET /roles
// Returns the 20 affected person roles reference data.
func (h *IACEHandler) ListRoles(c *gin.Context) {
roles, err := h.store.ListRoles(c.Request.Context())
if err != nil {
// Fallback: return hardcoded roles if DB table not yet migrated
roles = []iace.RoleInfo{
{ID: "operator", LabelDE: "Maschinenbediener", LabelEN: "Machine Operator", Sort: 1},
{ID: "setter", LabelDE: "Einrichter", LabelEN: "Setter", Sort: 2},
{ID: "maintenance_tech", LabelDE: "Wartungstechniker", LabelEN: "Maintenance Technician", Sort: 3},
{ID: "service_tech", LabelDE: "Servicetechniker", LabelEN: "Service Technician", Sort: 4},
{ID: "cleaning_staff", LabelDE: "Reinigungspersonal", LabelEN: "Cleaning Staff", Sort: 5},
{ID: "production_manager", LabelDE: "Produktionsleiter", LabelEN: "Production Manager", Sort: 6},
{ID: "safety_officer", LabelDE: "Sicherheitsbeauftragter", LabelEN: "Safety Officer", Sort: 7},
{ID: "electrician", LabelDE: "Elektriker", LabelEN: "Electrician", Sort: 8},
{ID: "software_engineer", LabelDE: "Softwareingenieur", LabelEN: "Software Engineer", Sort: 9},
{ID: "maintenance_manager", LabelDE: "Instandhaltungsleiter", LabelEN: "Maintenance Manager", Sort: 10},
{ID: "plant_operator", LabelDE: "Anlagenfahrer", LabelEN: "Plant Operator", Sort: 11},
{ID: "qa_inspector", LabelDE: "Qualitaetssicherung", LabelEN: "Quality Assurance", Sort: 12},
{ID: "logistics_staff", LabelDE: "Logistikpersonal", LabelEN: "Logistics Staff", Sort: 13},
{ID: "subcontractor", LabelDE: "Fremdfirma / Subunternehmer", LabelEN: "Subcontractor", Sort: 14},
{ID: "visitor", LabelDE: "Besucher", LabelEN: "Visitor", Sort: 15},
{ID: "auditor", LabelDE: "Auditor", LabelEN: "Auditor", Sort: 16},
{ID: "it_admin", LabelDE: "IT-Administrator", LabelEN: "IT Administrator", Sort: 17},
{ID: "remote_service", LabelDE: "Fernwartungsdienst", LabelEN: "Remote Service", Sort: 18},
{ID: "plant_owner", LabelDE: "Betreiber", LabelEN: "Plant Owner / Operator", Sort: 19},
{ID: "emergency_responder", LabelDE: "Notfallpersonal", LabelEN: "Emergency Responder", Sort: 20},
}
}
if roles == nil {
roles = []iace.RoleInfo{}
}
c.JSON(http.StatusOK, gin.H{
"roles": roles,
"total": len(roles),
})
}
// ListEvidenceTypes handles GET /evidence-types
// Returns the 50 evidence/verification types reference data.
func (h *IACEHandler) ListEvidenceTypes(c *gin.Context) {
types, err := h.store.ListEvidenceTypes(c.Request.Context())
if err != nil {
// Fallback: return empty if not migrated
types = []iace.EvidenceTypeInfo{}
}
if types == nil {
types = []iace.EvidenceTypeInfo{}
}
category := c.Query("category")
if category != "" {
var filtered []iace.EvidenceTypeInfo
for _, t := range types {
if t.Category == category {
filtered = append(filtered, t)
}
}
if filtered == nil {
filtered = []iace.EvidenceTypeInfo{}
}
types = filtered
}
c.JSON(http.StatusOK, gin.H{
"evidence_types": types,
"total": len(types),
})
}

View File

@@ -48,185 +48,194 @@ func GetControlsLibrary() []ControlLibraryEntry {
{ID: "CTRL.REQ.028", Domain: "REQ", Title: "Kalibrierungsanforderungen definiert", Description: "Anforderungen an Kalibrierung und Messkettenpruefung fuer sicherheitsrelevante Sensoren sind spezifiziert.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "mechanical_hazard"}, EvidenceExamples: []string{"Kalibrierplan", "Kalibrieranforderungen"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.REQ.029", Domain: "REQ", Title: "Produktlebenszyklusanforderungen erfasst", Description: "Anforderungen fuer den gesamten Produktlebenszyklus (Inbetriebnahme bis Ausserbetriebnahme) sind dokumentiert.", PriorityHint: "medium", MapsToHazardCategories: []string{"maintenance_hazard"}, EvidenceExamples: []string{"Lebenszyklusplan", "End-of-Life-Konzept"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.REQ.030", Domain: "REQ", Title: "Notfallplanung als Anforderung", Description: "Anforderungen fuer Notfallbetrieb, Degradation und Wiederanlauf nach Ausfall sind spezifiziert.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "communication_failure"}, EvidenceExamples: []string{"Notfallplan-Anforderungen", "Degradationskonzept"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
// ── Domain ARCH (Architecture & Design) ───────────────────────────────
{ID: "CTRL.ARCH.001", Domain: "ARCH", Title: "Redundanzkonzept implementiert", Description: "Sicherheitsrelevante Funktionen sind durch Redundanz abgesichert, sodass ein Einzelfehler nicht zum Ausfall fuehrt.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Redundanzkonzept", "FMEA-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.002", Domain: "ARCH", Title: "Fail-Safe-Verhalten definiert", Description: "Das System geht bei Erkennung eines Fehlers in einen sicheren Zustand ueber, der keine Gefaehrdung verursacht.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "software_fault"}, EvidenceExamples: []string{"Fail-Safe-Konzept", "Safe-State-Beschreibung"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.003", Domain: "ARCH", Title: "Diagnostics Coverage sichergestellt", Description: "Die Diagnosedeckung (DC) fuer alle sicherheitsrelevanten Hardwarekomponenten ist gemaess SIL/PL-Anforderung erreicht.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"DC-Nachweis", "Diagnosekonzept"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.004", Domain: "ARCH", Title: "Diverse Softwareimplementierung", Description: "Fuer SIL3/SIL4-Anforderungen werden zwei unabhaengig entwickelte Softwareversionen eingesetzt.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault", "safety_function_failure"}, EvidenceExamples: []string{"Diversitaetsnachweis", "Entwicklungsprozess-Dokument"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.ARCH.005", Domain: "ARCH", Title: "Watchdog-Timer implementiert", Description: "Ein hardwarebasierter Watchdog-Timer ueberwacht die korrekte Ausfuehrung der Safety-Software.", PriorityHint: "critical", MapsToHazardCategories: []string{"timing_error", "software_fault"}, EvidenceExamples: []string{"Watchdog-Designdokument", "Testnachweis"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.006", Domain: "ARCH", Title: "Safe-State-Transition spezifiziert", Description: "Alle Zustandsuebergaenge in den sicheren Zustand sind vollstaendig definiert und getestet.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "mode_confusion"}, EvidenceExamples: []string{"Zustandsdiagramm", "Transition-Testprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.007", Domain: "ARCH", Title: "Fehlererkennung implementiert", Description: "Mechanismen zur Erkennung von Einzel- und Mehrfachfehlern (z.B. CRC, ECC, Parity) sind implementiert.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault", "electrical_hazard"}, EvidenceExamples: []string{"Fehlererkennungskonzept", "CRC-Testnachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.008", Domain: "ARCH", Title: "Modulares Design umgesetzt", Description: "Die Systemarchitektur ist modular aufgebaut, sodass sicherheitsrelevante Module klar abgegrenzt sind.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault", "integration_error"}, EvidenceExamples: []string{"Architekturdiagramm", "Modulbeschreibung"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.ARCH.009", Domain: "ARCH", Title: "Partitionierung safety/non-safety", Description: "Safety- und Non-Safety-Softwareteile sind klar partitioniert und gegenseitige Beeinflussung ist unterbunden.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "software_fault"}, EvidenceExamples: []string{"Partitionierungsnachweis", "MPU-Konfiguration"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.ARCH.010", Domain: "ARCH", Title: "Hardware-Absicherung sicherheitsrelevanter Funktionen", Description: "Sicherheitsrelevante Hardware-Pfade sind durch dedizierte Schutzschaltungen gegen Fehler abgesichert.", PriorityHint: "critical", MapsToHazardCategories: []string{"electrical_hazard", "safety_function_failure"}, EvidenceExamples: []string{"HW-Schutzkonzept", "Schaltplan-Review"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.011", Domain: "ARCH", Title: "Sicherer Bootvorgang implementiert", Description: "Der Bootvorgang prueft die Integritaet der Software bevor sicherheitsrelevante Funktionen aktiviert werden.", PriorityHint: "high", MapsToHazardCategories: []string{"firmware_corruption", "software_fault"}, EvidenceExamples: []string{"Secure-Boot-Konzept", "Testprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.ARCH.012", Domain: "ARCH", Title: "Speicherpartitionierung umgesetzt", Description: "Speicherbereiche fuer Safety- und Non-Safety-Code sind durch Hardware (MPU/MMU) getrennt.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"MPU-Konfigurationsdokument", "Speicher-Map"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.ARCH.013", Domain: "ARCH", Title: "Zufaellige Fehlerrate reduziert", Description: "Massnahmen zur Reduzierung der zufaelligen Hardwarefehlerrate (PFH/PFD) sind im Design beruecksichtigt.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure", "electrical_hazard"}, EvidenceExamples: []string{"PFH-Berechnung", "FMEDA-Nachweis"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.014", Domain: "ARCH", Title: "Sicherheitsarchitektur dokumentiert", Description: "Die Sicherheitsarchitektur ist vollstaendig dokumentiert und durch Review freigegeben.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Sicherheitsarchitektur-Dokument", "Review-Protokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.ARCH.015", Domain: "ARCH", Title: "Redundante Kommunikation", Description: "Sicherheitsrelevante Kommunikationspfade sind redundant ausgelegt oder mit Fehlererkennungsmechanismen abgesichert.", PriorityHint: "high", MapsToHazardCategories: []string{"communication_failure", "safety_function_failure"}, EvidenceExamples: []string{"Kommunikationsarchitektur", "Redundanznachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.016", Domain: "ARCH", Title: "Independent Safety Monitor", Description: "Ein unabhaengiger Safety-Monitor ueberwacht die Hauptsicherheitsfunktion und kann diese deaktivieren.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Monitor-Designdokument", "Unabhaengigkeitsnachweis"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.017", Domain: "ARCH", Title: "Safety-Integrity-Architektur nachgewiesen", Description: "Die Systemarchitektur erfuellt die Anforderungen des zugewiesenen SIL/PL gemaess IEC 61508 oder ISO 13849.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"SIL-Architekturnachweis", "PL-Zertifikat"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.018", Domain: "ARCH", Title: "Diversitaere Hardware eingesetzt", Description: "Fuer kritische Sicherheitsfunktionen werden unterschiedliche Hardwaretypen eingesetzt, um Systematikfehler zu vermeiden.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure", "electrical_hazard"}, EvidenceExamples: []string{"Diversitaetsnachweis", "BOM-Review"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.019", Domain: "ARCH", Title: "Systemgrenzen definiert", Description: "Die Systemgrenzen und Schnittstellen zu anderen Systemen und Betreibern sind klar definiert.", PriorityHint: "high", MapsToHazardCategories: []string{"integration_error"}, EvidenceExamples: []string{"Systemgrenzendokument", "Interface-Control-Document"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.ARCH.020", Domain: "ARCH", Title: "Energiemanagement-Architektur", Description: "Die Architektur stellt sicher, dass bei Energieausfall oder -schwankung ein sicherer Zustand erreicht wird.", PriorityHint: "high", MapsToHazardCategories: []string{"electrical_hazard", "safety_function_failure"}, EvidenceExamples: []string{"Energiemanagement-Konzept", "UPS-Design"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.021", Domain: "ARCH", Title: "Schutzmassnahmen Hardware implementiert", Description: "Hardware-Schutzmassnahmen (Ueberstrom, Ueberspannung, thermischer Schutz) sind im Design integriert.", PriorityHint: "medium", MapsToHazardCategories: []string{"electrical_hazard", "thermal_hazard"}, EvidenceExamples: []string{"HW-Schutzschaltungs-Nachweis", "Pruefprotokoll"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.022", Domain: "ARCH", Title: "Thermisches Design umgesetzt", Description: "Waermemanagement und thermisches Design stellen den Betrieb innerhalb der zulaessigen Temperaturgrenzen sicher.", PriorityHint: "medium", MapsToHazardCategories: []string{"thermal_hazard"}, EvidenceExamples: []string{"Thermisches Design-Dokument", "Temperatursimulation"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.023", Domain: "ARCH", Title: "EMV-Design beruecksichtigt", Description: "EMV-gerechtes Design (Schirmung, Filterung, Layoutregeln) wurde bei der Leiterplattenentwicklung angewendet.", PriorityHint: "medium", MapsToHazardCategories: []string{"emc_hazard", "electrical_hazard"}, EvidenceExamples: []string{"EMV-Design-Review", "EMV-Testbericht"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.024", Domain: "ARCH", Title: "Mechanisches Schutzkonzept umgesetzt", Description: "Mechanische Schutzmassnahmen (Gehaeuse, IP-Schutzart, Vibrationsschutz) sind dem Einsatzbereich angepasst.", PriorityHint: "medium", MapsToHazardCategories: []string{"mechanical_hazard", "environmental_hazard"}, EvidenceExamples: []string{"IP-Zertifikat", "Vibrationstest-Protokoll"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.025", Domain: "ARCH", Title: "Wartungsarchitektur geplant", Description: "Die Systemarchitektur unterstuetzt planmaessige Wartung ohne Deaktivierung aller Sicherheitsfunktionen.", PriorityHint: "medium", MapsToHazardCategories: []string{"maintenance_hazard"}, EvidenceExamples: []string{"Wartungskonzept", "Architektur-Review"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.026", Domain: "ARCH", Title: "Testpunkte im Design vorgesehen", Description: "Das Hardware-Design enthaelt dedizierte Testpunkte fuer Produktionstest und Instandhaltung.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Testpunkt-Plan", "Layout-Review"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.ARCH.027", Domain: "ARCH", Title: "Sicherer Zustand definiert und erreichbar", Description: "Der sichere Zustand des Systems ist eindeutig definiert und unter allen Fehlerbedingungen erreichbar.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "mode_confusion"}, EvidenceExamples: []string{"Safe-State-Definition", "Zustandsautomat"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.028", Domain: "ARCH", Title: "Safe-State-Uebergang getestet", Description: "Der Uebergang in den sicheren Zustand wurde unter realen Fehlerbedingungen erprobt und dokumentiert.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Safe-State-Testprotokoll", "Fehler-Injektionstest"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.ARCH.029", Domain: "ARCH", Title: "Back-to-Back-Test-Architektur unterstuetzt", Description: "Die Architektur ermoeglicht Back-to-Back-Tests zwischen diversitaeren Implementierungen.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"B2B-Test-Konzept", "Vergleichstest-Protokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.ARCH.030", Domain: "ARCH", Title: "Diagnosemassnahmen vollstaendig", Description: "Alle Diagnosemassnahmen sind vollstaendig spezifiziert, implementiert und auf DC-Zielwert ueberprueft.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Diagnosekonzept", "DC-Berechnung"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
// ── Domain SWDEV (Software Development) ───────────────────────────────
{ID: "CTRL.SWDEV.001", Domain: "SWDEV", Title: "SW-Safety-Plan erstellt", Description: "Ein Software-Safety-Plan mit Zielen, Aktivitaeten und Verantwortlichkeiten ist dokumentiert und freigegeben.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault", "safety_function_failure"}, EvidenceExamples: []string{"SW-Safety-Plan", "Freigabeprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.002", Domain: "SWDEV", Title: "MISRA-C Compliance sichergestellt", Description: "Der C-Quellcode erfuellt die MISRA-C-Regeln fuer sicherheitskritische Software.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"MISRA-Pruefbericht", "Abweichungsliste"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.003", Domain: "SWDEV", Title: "Statische Code-Analyse durchgefuehrt", Description: "Statische Code-Analyse mit einem qualifizierten Tool wurde durchgefuehrt und alle Befunde bewertet.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Statische-Analyse-Bericht", "Tool-Qualifikationsnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.004", Domain: "SWDEV", Title: "Code-Review-Prozess etabliert", Description: "Alle sicherheitsrelevanten Codeaenderungen werden durch einen unabhaengigen Review freigegeben.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Review-Protokolle", "Review-Checkliste"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.005", Domain: "SWDEV", Title: "Defensiv-Programmierung angewendet", Description: "Defensive Programmiertechniken (Eingabevalidierung, Assertions, Fehlerbehandlung) sind konsequent eingesetzt.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault", "integration_error"}, EvidenceExamples: []string{"Coding-Standard", "Code-Review-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.006", Domain: "SWDEV", Title: "Unit-Tests fuer Safety-Funktionen", Description: "Alle sicherheitsrelevanten Softwaremodule haben dokumentierte Unit-Tests mit definierten Abbruchkriterien.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Unit-Test-Berichte", "Testplan"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.007", Domain: "SWDEV", Title: "Code-Coverage-Analyse durchgefuehrt", Description: "Die Testabdeckung (Statement, Branch, MC/DC) wurde gemessen und entspricht den SIL-Anforderungen.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Coverage-Bericht", "MC/DC-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.008", Domain: "SWDEV", Title: "Konfigurations-Management implementiert", Description: "Alle Softwareartefakte stehen unter Konfigurationsmanagement mit nachvollziehbarer Versionshistorie.", PriorityHint: "critical", MapsToHazardCategories: []string{"configuration_error", "software_fault"}, EvidenceExamples: []string{"CM-Plan", "Repository-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.009", Domain: "SWDEV", Title: "Compiler-Warnungen aktiviert und bewertet", Description: "Alle Compiler-Warnungen sind aktiviert und alle Warnungen sind bewertet und beseitigt oder dokumentiert begründet.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Compiler-Log", "Warnungsliste"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.010", Domain: "SWDEV", Title: "RTOS-Nutzung qualifiziert", Description: "Das eingesetzte Echtzeitbetriebssystem ist fuer den Sicherheitsintegritaetslevel qualifiziert.", PriorityHint: "critical", MapsToHazardCategories: []string{"timing_error", "software_fault"}, EvidenceExamples: []string{"RTOS-Qualifikationsnachweis", "Tool-Qualifikation"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.011", Domain: "SWDEV", Title: "Speicherschutz aktiviert", Description: "Hardware-Speicherschutz (MPU) ist aktiviert und verhindert unerlaubten Speicherzugriff zwischen Modulen.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"MPU-Konfiguration", "Testnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.012", Domain: "SWDEV", Title: "Stack-Analyse durchgefuehrt", Description: "Der maximale Stack-Verbrauch aller Tasks wurde analysiert und Stackgroessen sind angemessen dimensioniert.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault", "timing_error"}, EvidenceExamples: []string{"Stack-Analyse-Bericht", "WCSA-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.013", Domain: "SWDEV", Title: "Deadlock-Analyse durchgefuehrt", Description: "Potenzielle Deadlocks und Race-Conditions wurden analysiert und ausgeschlossen.", PriorityHint: "high", MapsToHazardCategories: []string{"timing_error", "software_fault"}, EvidenceExamples: []string{"Deadlock-Analyse", "Synchronisationsnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.014", Domain: "SWDEV", Title: "WCET-Analyse durchgefuehrt", Description: "Worst-Case Execution Times aller sicherheitsrelevanten Tasks wurden analysiert und sind innerhalb der Zeitbudgets.", PriorityHint: "high", MapsToHazardCategories: []string{"timing_error"}, EvidenceExamples: []string{"WCET-Analyse-Bericht", "Timing-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.015", Domain: "SWDEV", Title: "SW-Integrationsstrategie definiert", Description: "Die Software-Integrationsstrategie (Bottom-Up, Top-Down) ist geplant und dokumentiert.", PriorityHint: "high", MapsToHazardCategories: []string{"integration_error", "software_fault"}, EvidenceExamples: []string{"Integrationsplan", "Teststrategie"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.016", Domain: "SWDEV", Title: "SW-Sicherheitstests spezifiziert", Description: "Software-Sicherheitstests sind spezifiziert und abdecken alle sicherheitsrelevanten Funktionen und Fehlerszenarien.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault", "safety_function_failure"}, EvidenceExamples: []string{"Sicherheitstest-Spezifikation", "Testprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.017", Domain: "SWDEV", Title: "Coding-Standards definiert", Description: "Einheitliche Coding-Standards sind definiert, kommuniziert und ihre Einhaltung wird automatisch ueberprueft.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Coding-Standard-Dokument", "Linter-Konfiguration"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.018", Domain: "SWDEV", Title: "Dokumentation SW-Design vollstaendig", Description: "Die Software-Design-Dokumentation ist vollstaendig, aktuell und durch Review freigegeben.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"SW-Design-Dokument", "Doxygen-Ausgabe"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.019", Domain: "SWDEV", Title: "Fehlerbehandlung vollstaendig implementiert", Description: "Alle Fehlerzustaende sind vollstaendig behandelt — kein unbehandelter Fehler kann zum Systemabsturz fuehren.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault", "safety_function_failure"}, EvidenceExamples: []string{"Fehlerbehandlungs-Matrix", "Code-Review-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.020", Domain: "SWDEV", Title: "Modul-Interface-Definition vorhanden", Description: "Alle Software-Modul-Interfaces sind vollstaendig und formell spezifiziert.", PriorityHint: "high", MapsToHazardCategories: []string{"integration_error"}, EvidenceExamples: []string{"Interface-Spezifikation", "API-Dokumentation"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.021", Domain: "SWDEV", Title: "Versionskontrolle fuer alle Artefakte", Description: "Alle Softwareartefakte (Code, Tests, Dokumentation) werden in einem Versionskontrollsystem verwaltet.", PriorityHint: "medium", MapsToHazardCategories: []string{"configuration_error"}, EvidenceExamples: []string{"Git-Repository", "Taggin-Policy"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.022", Domain: "SWDEV", Title: "Build-Reproduzierbarkeit sichergestellt", Description: "Der Build-Prozess ist vollstaendig automatisiert und reproduzierbar (gleiche Eingaben erzeugen gleiche Ausgaben).", PriorityHint: "medium", MapsToHazardCategories: []string{"configuration_error", "software_fault"}, EvidenceExamples: []string{"Build-Skript", "CI/CD-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.023", Domain: "SWDEV", Title: "Abhaengigkeitsanalyse durchgefuehrt", Description: "Alle externen Softwareabhaengigkeiten wurden analysiert, bewertet und ihre Kompatibilitaet ist sichergestellt.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault", "update_failure"}, EvidenceExamples: []string{"SBOM", "Abhaengigkeits-Review"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.024", Domain: "SWDEV", Title: "Sicheres API-Design umgesetzt", Description: "APIs sind nach Security-by-Design-Prinzipien entwickelt und gegen Missbrauch abgesichert.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "software_fault"}, EvidenceExamples: []string{"API-Sicherheits-Review", "Threat-Model"}, ReductionType: "design", Applicable: []string{"sw", "ai"}},
{ID: "CTRL.SWDEV.025", Domain: "SWDEV", Title: "Input-Validierung implementiert", Description: "Alle externen Eingaben werden validiert und ungueltige Eingaben werden sicher behandelt.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault", "unauthorized_access"}, EvidenceExamples: []string{"Validierungs-Nachweis", "Fuzzing-Testbericht"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.026", Domain: "SWDEV", Title: "Logging in sicherheitsrelevanter SW", Description: "Sicherheitsrelevante Software-Ereignisse werden protokolliert und sind fuer die Diagnose verfuegbar.", PriorityHint: "medium", MapsToHazardCategories: []string{"logging_audit_failure"}, EvidenceExamples: []string{"Logging-Konzept", "Log-Beispiele"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.027", Domain: "SWDEV", Title: "Exception-Handling vollstaendig", Description: "Alle moeglichen Ausnahmen (Exceptions) sind behandelt und fuehren zu einem definierten sicheren Zustand.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Exception-Handler-Review", "Testprotokoll"}, ReductionType: "protective", Applicable: []string{"sw"}},
{ID: "CTRL.SWDEV.028", Domain: "SWDEV", Title: "SW-Update-Mechanismus sicher implementiert", Description: "Der Software-Update-Mechanismus validiert Signatur und Integritaet vor der Installation.", PriorityHint: "medium", MapsToHazardCategories: []string{"update_failure", "firmware_corruption"}, EvidenceExamples: []string{"Update-Mechanismus-Design", "Signaturpruefungsnachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.029", Domain: "SWDEV", Title: "Selbsttest-Routinen implementiert", Description: "Das System fuehrt beim Start und zyklisch Selbsttests der sicherheitsrelevanten Funktionen durch.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Selbsttest-Konzept", "Testabdeckungsnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.SWDEV.030", Domain: "SWDEV", Title: "Parameterpruefung implementiert", Description: "Alle Konfigurationsparameter werden beim Start und nach Aenderungen auf Gueltigkeit geprueft.", PriorityHint: "medium", MapsToHazardCategories: []string{"configuration_error", "software_fault"}, EvidenceExamples: []string{"Parameterpruef-Nachweis", "Out-of-Range-Testprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.SWDEV.031", Domain: "SWDEV", Title: "Transiente Fehlertoleranz implementiert", Description: "Die Software toleriert transiente Fehler (Bitflips, EMV-Stoerungen) und stellt den korrekten Betrieb wieder her.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault", "emc_hazard"}, EvidenceExamples: []string{"Fehlertoleranz-Konzept", "Soft-Error-Testnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.032", Domain: "SWDEV", Title: "Watchdog-SW korrekt implementiert", Description: "Die Software-Watchdog-Behandlung verhindert falsche Bediening und stellt echte Ueberwachung sicher.", PriorityHint: "medium", MapsToHazardCategories: []string{"timing_error", "software_fault"}, EvidenceExamples: []string{"Watchdog-SW-Review", "Watchdog-Testprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.033", Domain: "SWDEV", Title: "Sicherer Neustart implementiert", Description: "Der Systemstart nach Fehler oder Watchdog-Reset fuehrt zu einem sicheren Ausgangszustand.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault", "safety_function_failure"}, EvidenceExamples: []string{"Reset-Handling-Dokument", "Neustart-Testprotokoll"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.034", Domain: "SWDEV", Title: "Boot-Integritaetspruefung implementiert", Description: "Beim Bootvorgang wird die Integritaet aller sicherheitsrelevanten Softwarekomponenten verifiziert.", PriorityHint: "medium", MapsToHazardCategories: []string{"firmware_corruption", "software_fault"}, EvidenceExamples: []string{"Boot-Integritaets-Nachweis", "CRC-Testprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.SWDEV.035", Domain: "SWDEV", Title: "Sicherheits-SW-Architektur dokumentiert", Description: "Die Sicherheitssoftware-Architektur ist vollstaendig dokumentiert inkl. Datenfluessen und Kontrollfluss.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"SW-Architektur-Dokument", "Datenflussdiagramm"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.036", Domain: "SWDEV", Title: "SW-Lifecycle-Plan erstellt", Description: "Der Software-Lifecycle-Plan definiert alle Phasen von Planung bis Ausserdienststellung.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"SW-Lifecycle-Plan", "Meilensteinplan"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.037", Domain: "SWDEV", Title: "Baseline-Management implementiert", Description: "Konfigurationsbaselines werden zu definierten Meilensteinen erstellt und versioniert.", PriorityHint: "medium", MapsToHazardCategories: []string{"configuration_error"}, EvidenceExamples: []string{"Baseline-Register", "CM-Tool-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.038", Domain: "SWDEV", Title: "SW-Verifizierungsplan erstellt", Description: "Der Software-Verifizierungsplan legt Methoden, Werkzeuge und Verantwortlichkeiten fuer alle Teststufen fest.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Verifizierungsplan", "Testmatrix"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.039", Domain: "SWDEV", Title: "Qualitaetsmetriken definiert und gemessen", Description: "Softwarequalitaetsmetriken (Complexity, Coupling, Defectrate) werden erhoben und bewertet.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Qualitaetsmetriken-Bericht", "Code-Analyse-Tool-Ausgabe"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.SWDEV.040", Domain: "SWDEV", Title: "Threat-Modeling fuer SW durchgefuehrt", Description: "Ein Threat-Modeling (STRIDE, PASTA) wurde fuer die Software-Architektur durchgefuehrt und Massnahmen abgeleitet.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "software_fault"}, EvidenceExamples: []string{"Threat-Model-Dokument", "Massnahmenplan"}, ReductionType: "design", Applicable: []string{"sw", "ai"}},
// ── Domain VER (Verification & Validation) ────────────────────────────
{ID: "CTRL.VER.001", Domain: "VER", Title: "Fault-Injection-Test durchgefuehrt", Description: "Fehlerinjektionstests wurden systematisch durchgefuehrt um die Fehlerreaktionen des Systems zu validieren.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "software_fault"}, EvidenceExamples: []string{"Fault-Injection-Testprotokoll", "Testplan"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.002", Domain: "VER", Title: "WCET-Messung validiert", Description: "Worst-Case Execution Times wurden messtechnisch validiert und entsprechen den Analyseergebnissen.", PriorityHint: "critical", MapsToHazardCategories: []string{"timing_error"}, EvidenceExamples: []string{"WCET-Messprokoll", "Trace-Analyse"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.VER.003", Domain: "VER", Title: "HIL-Test durchgefuehrt", Description: "Hardware-in-the-Loop-Tests wurden mit repraesentativen Testfaellen und Fehlerszenarien durchgefuehrt.", PriorityHint: "critical", MapsToHazardCategories: []string{"integration_error", "safety_function_failure"}, EvidenceExamples: []string{"HIL-Testprotokoll", "HIL-Testplan"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.004", Domain: "VER", Title: "Boundary-Value-Test durchgefuehrt", Description: "Grenzwertanalyse und Aequivalenzklassentest wurden fuer alle Eingangsparameter durchgefuehrt.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault", "safety_boundary_violation"}, EvidenceExamples: []string{"Boundary-Test-Protokoll", "Testspezifikation"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.VER.005", Domain: "VER", Title: "Penetrationstest durchgefuehrt", Description: "Penetrationstests durch qualifizierte Tester wurden durchgefuehrt und alle Findings bewertet.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Penetrationstest-Bericht", "Finding-Tracking"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.VER.006", Domain: "VER", Title: "Regressionstest etabliert", Description: "Automatisierte Regressionstests werden bei jeder Codeaenderung ausgefuehrt um Regressionen zu erkennen.", PriorityHint: "critical", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Regressionstest-Protokoll", "CI-Pipeline-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.VER.007", Domain: "VER", Title: "SIL-Verifikation abgeschlossen", Description: "Die Verifikation des geforderten SIL/PL wurde durch qualifizierte Institution durchgefuehrt und positiv bewertet.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"SIL-Verifikationsbericht", "Zertifikat"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.008", Domain: "VER", Title: "Sicherheitsfunktions-Test bestanden", Description: "Alle spezifizierten Sicherheitsfunktionen wurden systematisch getestet und alle Tests bestanden.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Sicherheitsfunktions-Testprotokoll", "Akzeptanzkriterien-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.009", Domain: "VER", Title: "Lasttest durchgefuehrt", Description: "Lasttests unter maximaler Systembelastung wurden durchgefuehrt und alle Sicherheitsfunktionen behalten ihr Verhalten.", PriorityHint: "critical", MapsToHazardCategories: []string{"timing_error", "software_fault"}, EvidenceExamples: []string{"Lasttest-Protokoll", "Ressourcenauslastungs-Bericht"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.010", Domain: "VER", Title: "Stresstest unter Extrembedingungen", Description: "Stresstests unter Extrembedingungen (Temperatur, Spannung, Vibration) wurden erfolgreich durchgefuehrt.", PriorityHint: "high", MapsToHazardCategories: []string{"environmental_hazard", "safety_function_failure"}, EvidenceExamples: []string{"Stresstest-Protokoll", "Klimatest-Bericht"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.011", Domain: "VER", Title: "EMV-Test bestanden", Description: "EMV-Tests nach anwendbaren Normen wurden in akkreditiertem Labor durchgefuehrt und bestanden.", PriorityHint: "high", MapsToHazardCategories: []string{"emc_hazard", "electrical_hazard"}, EvidenceExamples: []string{"EMV-Pruefbericht", "Laborzertifikat"}, ReductionType: "protective", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.012", Domain: "VER", Title: "Umgebungstest abgeschlossen", Description: "Umgebungstests (Klimatest, Vibration, Schock) nach anwendbaren Normen wurden bestanden.", PriorityHint: "high", MapsToHazardCategories: []string{"environmental_hazard", "mechanical_hazard"}, EvidenceExamples: []string{"Umgebungstest-Berichte", "Klimatestprotokoll"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.013", Domain: "VER", Title: "Interface-Test durchgefuehrt", Description: "Alle definierten System-Interfaces wurden auf Konformitaet und Fehlverhalten getestet.", PriorityHint: "high", MapsToHazardCategories: []string{"integration_error", "communication_failure"}, EvidenceExamples: []string{"Interface-Testprotokoll", "Konformitaetsnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.014", Domain: "VER", Title: "Integrations-Qualifikation abgeschlossen", Description: "Die Systemintegration wurde schrittweise qualifiziert und alle Integrationstest bestanden.", PriorityHint: "high", MapsToHazardCategories: []string{"integration_error"}, EvidenceExamples: []string{"Integrationstest-Protokoll", "Qualifikationsplan"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.015", Domain: "VER", Title: "System-Abnahmetest bestanden", Description: "Der System-Abnahmetest wurde durch Kunden und/oder Zertifizierungsstelle erfolgreich durchgefuehrt.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"SAT-Protokoll", "Abnahme-Zertifikat"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.VER.016", Domain: "VER", Title: "Sicherheitsnachweise vollstaendig", Description: "Alle erforderlichen Sicherheitsnachweise sind vollstaendig, aktuell und von der Zertifizierungsstelle anerkannt.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Safety-Case", "Zertifikat"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.VER.017", Domain: "VER", Title: "Unabhaengige Verifikation durchgefuehrt", Description: "Eine unabhaengige Verifikation (IV&V) durch eine separate Stelle wurde fuer alle SIL3/4-Anforderungen durchgefuehrt.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"IV&V-Bericht", "Unabhaengigkeitsnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.018", Domain: "VER", Title: "Safety-Case dokumentiert", Description: "Der Safety-Case stellt strukturiert dar wie alle Sicherheitsziele durch Massnahmen und Nachweise erfuellt sind.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Safety-Case-Dokument", "Argumentation-Baum"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.VER.019", Domain: "VER", Title: "Code-Coverage-Nachweis erbracht", Description: "Der geforderte Code-Coverage-Grad (Statement/Branch/MC/DC) wurde nachgewiesen und dokumentiert.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Coverage-Bericht", "MC/DC-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.VER.020", Domain: "VER", Title: "Fehlermodell-Test abgeschlossen", Description: "Tests basierend auf dem Fehlermodell (Fehlerguppe, Fehlerrate) wurden durchgefuehrt und ausgewertet.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "software_fault"}, EvidenceExamples: []string{"Fehlermodell-Test-Protokoll", "FMEA-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.VER.021", Domain: "VER", Title: "Feldbus-Konformitaetstest bestanden", Description: "Konformitaetstests fuer alle eingesetzten Feldbuskommunikationen wurden erfolgreich abgeschlossen.", PriorityHint: "medium", MapsToHazardCategories: []string{"communication_failure", "integration_error"}, EvidenceExamples: []string{"Konformitaetstest-Zertifikat", "Pruefprotokoll"}, ReductionType: "protective", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.022", Domain: "VER", Title: "Kalibrierungsverifikation abgeschlossen", Description: "Die Kalibrierung aller sicherheitsrelevanten Messwerterfassungen wurde verifiziert und dokumentiert.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "mechanical_hazard"}, EvidenceExamples: []string{"Kalibrierprotokoll", "Messketten-Nachweis"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.023", Domain: "VER", Title: "Dokumentenpruefung durchgefuehrt", Description: "Alle sicherheitsrelevanten Dokumente wurden auf Vollstaendigkeit, Konsistenz und Korrektheit geprueft.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Dokumentenpruef-Protokoll", "Review-Checkliste"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.VER.024", Domain: "VER", Title: "Zuverlaessigkeitstest abgeschlossen", Description: "Zuverlaessigkeitstests (HALT, ALT) wurden durchgefuehrt und die Lebensdaueranforderungen bestanden.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"HALT-Bericht", "MTTF-Nachweis"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.025", Domain: "VER", Title: "Lebenszyklustest durchgefuehrt", Description: "Tests ueber den vollstaendigen Produktlebenszyklus (Alterung, Zyklen) wurden abgeschlossen.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "maintenance_hazard"}, EvidenceExamples: []string{"Lebenszyklustest-Protokoll", "Alterungstest-Bericht"}, ReductionType: "protective", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.026", Domain: "VER", Title: "Sicherheits-Audit abgeschlossen", Description: "Ein Sicherheits-Audit durch qualifizierte Auditoren wurde durchgefuehrt und alle Befunde behandelt.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Audit-Bericht", "Finding-Trackingprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.VER.027", Domain: "VER", Title: "Kompatibilitaetstest durchgefuehrt", Description: "Kompatibilitaetstests mit allen unterstuetzten Systemkonfigurationen und Softwareversionen wurden abgeschlossen.", PriorityHint: "medium", MapsToHazardCategories: []string{"integration_error", "configuration_error"}, EvidenceExamples: []string{"Kompatibilitaetstest-Matrix", "Testprotokoll"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.VER.028", Domain: "VER", Title: "Software-Review abgeschlossen", Description: "Formelle Software-Reviews (Inspektion, Walkthrough) wurden fuer alle sicherheitsrelevanten Module durchgefuehrt.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault"}, EvidenceExamples: []string{"Review-Protokoll", "Findings-Liste"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.VER.029", Domain: "VER", Title: "Factory-Acceptance-Test bestanden", Description: "Der Factory Acceptance Test (FAT) beim Hersteller wurde erfolgreich durchgefuehrt und dokumentiert.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"FAT-Protokoll", "Abnahme-Zertifikat"}, ReductionType: "protective", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.VER.030", Domain: "VER", Title: "Site-Acceptance-Test bestanden", Description: "Der Site Acceptance Test (SAT) am Einsatzort wurde erfolgreich durchgefuehrt und dokumentiert.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "integration_error"}, EvidenceExamples: []string{"SAT-Protokoll", "Inbetriebnahme-Zertifikat"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
// ── Domain CYBER (OT-Cybersecurity) ───────────────────────────────────
{ID: "CTRL.CYBER.001", Domain: "CYBER", Title: "Netzwerksegmentierung implementiert", Description: "OT- und IT-Netzwerke sind segmentiert und der Zugriff zwischen Zonen ist durch Firewalls kontrolliert.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"Netzwerkdiagramm", "Firewall-Regelwerk"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.002", Domain: "CYBER", Title: "Signierte Firmware-Updates", Description: "Alle Firmware-Updates werden vor der Installation kryptografisch auf Authentizitaet und Integritaet geprueft.", PriorityHint: "critical", MapsToHazardCategories: []string{"firmware_corruption", "unauthorized_access"}, EvidenceExamples: []string{"Signaturpruefungsnachweis", "Update-Prozess-Dokument"}, ReductionType: "protective", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.CYBER.003", Domain: "CYBER", Title: "MFA fuer Admin-Zugang", Description: "Multi-Faktor-Authentifizierung ist fuer alle administrativen Zugaenge zum System verpflichtend.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"MFA-Konfigurationsnachweis", "Zugangskontroll-Policy"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.004", Domain: "CYBER", Title: "IDS/IPS implementiert", Description: "Ein Intrusion Detection/Prevention System ueberwacht den Netzwerkverkehr auf Angriffsmuster.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"IDS-Konfigurationsnachweis", "Alert-Testprotokoll"}, ReductionType: "protective", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.005", Domain: "CYBER", Title: "SBOM vorhanden und aktuell", Description: "Eine vollstaendige Software Bill of Materials (SBOM) ist vorhanden und wird bei Releases aktualisiert.", PriorityHint: "critical", MapsToHazardCategories: []string{"firmware_corruption", "unauthorized_access"}, EvidenceExamples: []string{"SBOM-Dokument", "SBOM-Tool-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.CYBER.006", Domain: "CYBER", Title: "Schwachstellen-Scan durchgefuehrt", Description: "Regelmaessige Schwachstellen-Scans werden durchgefuehrt und Findings zeitgerecht behoben.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access", "firmware_corruption"}, EvidenceExamples: []string{"Scan-Bericht", "Remediation-Tracking"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.CYBER.007", Domain: "CYBER", Title: "Patch-Management etabliert", Description: "Ein strukturierter Patch-Management-Prozess stellt zeitnahe Behebung von Sicherheitsschwachstellen sicher.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access", "firmware_corruption"}, EvidenceExamples: []string{"Patch-Management-Policy", "Patch-Status-Report"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.008", Domain: "CYBER", Title: "Sichere Kommunikationsprotokolle (TLS/DTLS)", Description: "Alle Netzwerkkommunikationen nutzen TLS 1.2+ oder DTLS und schwache Ciphersuites sind deaktiviert.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"TLS-Konfigurationsnachweis", "SSL-Labs-Bericht"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.009", Domain: "CYBER", Title: "Firewall-Regeln minimiert", Description: "Firewall-Regeln folgen dem Whitelist-Prinzip — nur explizit erlaubter Verkehr ist zugelassen.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Firewall-Regelwerk-Review", "Penetrationstest-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.010", Domain: "CYBER", Title: "Portabsicherung implementiert", Description: "Alle nicht benoetigten Netzwerkports und Dienste sind deaktiviert und dokumentiert.", PriorityHint: "critical", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Port-Scan-Bericht", "Service-Haertungsdokument"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.011", Domain: "CYBER", Title: "VPN fuer Remote-Zugang", Description: "Fernzugriff auf OT-Systeme erfolgt ausschliesslich ueber verschluesselte VPN-Verbindungen.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"VPN-Konfigurationsnachweis", "Remote-Access-Policy"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.012", Domain: "CYBER", Title: "Passwort-Policy durchgesetzt", Description: "Eine Passwort-Policy mit Komplexitaetsanforderungen und Ablauffristen ist implementiert und technisch erzwungen.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Passwort-Policy", "Technischer Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.013", Domain: "CYBER", Title: "Brute-Force-Schutz aktiviert", Description: "Account-Lockout nach mehrfach fehlgeschlagenen Login-Versuchen ist implementiert und getestet.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Brute-Force-Test-Nachweis", "Konfigurationsprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.014", Domain: "CYBER", Title: "Session-Management sicher implementiert", Description: "Session-Tokens sind kryptografisch stark, Timeouts sind konfiguriert und Session-Fixation verhindert.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Session-Management-Review", "Penetrationstest-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw"}},
{ID: "CTRL.CYBER.015", Domain: "CYBER", Title: "Kryptografisch sichere Zufallszahlen", Description: "Kryptografisch sichere Zufallszahlengeneratoren (CSPRNG) werden fuer alle sicherheitsrelevanten Operationen genutzt.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access", "firmware_corruption"}, EvidenceExamples: []string{"CSPRNG-Nachweis", "Code-Review-Protokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.CYBER.016", Domain: "CYBER", Title: "PKI/Zertifikatsverwaltung etabliert", Description: "Eine Public Key Infrastructure (PKI) verwaltet alle Zertifikate mit definierten Lebenszyklen.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"PKI-Konzept", "Zertifikatsregister"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.017", Domain: "CYBER", Title: "Sicheres Schluesselspeichern (HSM/TPM)", Description: "Kryptografische Schluessel werden sicher in Hardware Security Modules (HSM) oder TPM-Chips gespeichert.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access", "firmware_corruption"}, EvidenceExamples: []string{"HSM-Konfigurationsnachweis", "Key-Management-Policy"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.018", Domain: "CYBER", Title: "Code-Signing implementiert", Description: "Alle ausfuehrbaren Softwarekomponenten sind mit verifizierbaren digitalen Signaturen versehen.", PriorityHint: "high", MapsToHazardCategories: []string{"firmware_corruption", "unauthorized_access"}, EvidenceExamples: []string{"Code-Signing-Prozess", "Signaturpruefungsnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw"}},
{ID: "CTRL.CYBER.019", Domain: "CYBER", Title: "Integrity-Monitoring aktiviert", Description: "Integritaets-Monitoring erkennt unautorisierten Zugriff auf kritische System- und Konfigurationsdateien.", PriorityHint: "high", MapsToHazardCategories: []string{"unauthorized_access", "configuration_error"}, EvidenceExamples: []string{"FIM-Konfigurationsnachweis", "Alert-Testprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.020", Domain: "CYBER", Title: "Log-Management etabliert", Description: "Zentralisiertes Log-Management stellt sichere Aufbewahrung und Unversehrtheit von Sicherheitslogs sicher.", PriorityHint: "high", MapsToHazardCategories: []string{"logging_audit_failure"}, EvidenceExamples: []string{"Log-Management-Konzept", "SIEM-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.021", Domain: "CYBER", Title: "SIEM-Integration vorhanden", Description: "Sicherheitsrelevante Ereignisse werden an ein SIEM-System weitergeleitet und korreliert.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "logging_audit_failure"}, EvidenceExamples: []string{"SIEM-Integrationsnachweis", "Usecase-Dokumentation"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.022", Domain: "CYBER", Title: "Vulnerability-Disclosure-Policy vorhanden", Description: "Eine oeffentliche Vulnerability Disclosure Policy (VDP) ist etabliert und ein Meldeprozess definiert.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"VDP-Dokument", "Bug-Bounty-Policy"}, ReductionType: "protective", Applicable: []string{"sw", "ai"}},
{ID: "CTRL.CYBER.023", Domain: "CYBER", Title: "Incident-Response-Plan vorhanden", Description: "Ein Cyber-Incident-Response-Plan definiert Eskalation, Rollen und Massnahmen fuer Sicherheitsvorfaelle.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "firmware_corruption"}, EvidenceExamples: []string{"Incident-Response-Plan", "Uebungsprotokoll"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.CYBER.024", Domain: "CYBER", Title: "Penetrationstest OT durchgefuehrt", Description: "OT-spezifische Penetrationstests unter Beruecksichtigung von Verduegbarkeitsanforderungen wurden durchgefuehrt.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"OT-Pentest-Bericht", "Finding-Tracking"}, ReductionType: "protective", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.CYBER.025", Domain: "CYBER", Title: "Security-by-Default konfiguriert", Description: "Alle Systeme werden mit sicheren Standardkonfigurationen ausgeliefert und unsichere Defaults sind deaktiviert.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "configuration_error"}, EvidenceExamples: []string{"Default-Konfigurationsnachweis", "Haertungs-Checkliste"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.026", Domain: "CYBER", Title: "Least-Privilege-Prinzip umgesetzt", Description: "Alle Benutzer, Prozesse und Dienste haben nur die Mindestberechtigungen die fuer ihre Funktion notwendig sind.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Berechtigungs-Matrix", "Access-Review-Protokoll"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.CYBER.027", Domain: "CYBER", Title: "Role-Based Access Control implementiert", Description: "RBAC stellt sicher dass Zugriffsrechte rollenbasiert vergeben und regelmaessig geprueft werden.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"RBAC-Konzept", "Rollen-Dokumentation"}, ReductionType: "design", Applicable: []string{"sw", "ctrl", "ai"}},
{ID: "CTRL.CYBER.028", Domain: "CYBER", Title: "Authentifizierung an allen Schnittstellen", Description: "Alle Kommunikationsschnittstellen erfordern starke Authentifizierung vor dem Datenzugriff.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"Schnittstellen-Auth-Nachweis", "API-Security-Review"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.029", Domain: "CYBER", Title: "Datenverschluesselung im Transit", Description: "Alle uebertragenen Daten sind Ende-zu-Ende verschluesselt, auch im internen Netzwerk.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"Verschluesselungsnachweis", "Traffic-Analyse"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.CYBER.030", Domain: "CYBER", Title: "Datenverschluesselung at Rest", Description: "Alle gespeicherten sensitiven Daten sind verschluesselt und Schluessel werden sicher verwaltet.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Verschluesselungskonzept", "Key-Management-Nachweis"}, ReductionType: "protective", Applicable: []string{"sw", "ctrl", "ai"}},
{ID: "CTRL.CYBER.031", Domain: "CYBER", Title: "Sicherer Fernzugriff kontrolliert", Description: "Fernzugriff ist auf bekannte Nutzer und Systeme beschraenkt und wird vollstaendig protokolliert.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Fernzugriffs-Policy", "Access-Log-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.032", Domain: "CYBER", Title: "Deaktivierung ungenutzter Dienste", Description: "Alle nicht benoetigten Netzwerkdienste, Protokolle und Benutzerschnittstellen sind deaktiviert.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Service-Inventar", "Haertungsnachweis"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.CYBER.033", Domain: "CYBER", Title: "Haertung Betriebssystem durchgefuehrt", Description: "Das Betriebssystem wurde gemaess anerkannten Haertungsleitfaeden (CIS Benchmark, BSI) konfiguriert.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "configuration_error"}, EvidenceExamples: []string{"Haertungs-Protokoll", "CIS-Benchmark-Bericht"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.034", Domain: "CYBER", Title: "Container-Sicherheit implementiert", Description: "Container-Images werden regelmaessig auf Schwachstellen gescannt und laufen mit minimalen Berechtigungen.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "software_fault"}, EvidenceExamples: []string{"Container-Scan-Bericht", "Pod-Security-Policy"}, ReductionType: "protective", Applicable: []string{"sw", "ai"}},
{ID: "CTRL.CYBER.035", Domain: "CYBER", Title: "Supply-Chain-Sicherheit beruecksichtigt", Description: "Software-Lieferketten-Risiken wurden bewertet und Massnahmen zur Absicherung sind implementiert.", PriorityHint: "medium", MapsToHazardCategories: []string{"firmware_corruption", "unauthorized_access"}, EvidenceExamples: []string{"Supply-Chain-Risikoanalyse", "SBOM-Nachweis"}, ReductionType: "design", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.CYBER.036", Domain: "CYBER", Title: "IEC-62443-Compliance-Assessment durchgefuehrt", Description: "Eine Konformitaetsbewertung gegenueber IEC 62443 fuer OT-Systeme wurde durchgefuehrt.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"IEC-62443-Gap-Assessment", "Compliance-Bericht"}, ReductionType: "protective", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.CYBER.037", Domain: "CYBER", Title: "Zero-Trust-Architektur umgesetzt", Description: "Zero-Trust-Prinzipien (Never Trust Always Verify) werden fuer alle Netzwerkzugriffe angewendet.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Zero-Trust-Architektur-Dokument", "Implementierungsnachweis"}, ReductionType: "design", Applicable: []string{"sw", "ctrl"}},
{ID: "CTRL.CYBER.038", Domain: "CYBER", Title: "Security-Training fuer Mitarbeiter", Description: "Regelmaessige Security-Awareness-Trainings werden fuer alle Mitarbeiter mit OT-Systemzugang durchgefuehrt.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access"}, EvidenceExamples: []string{"Trainingsprotokoll", "Teilnehmerliste"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.CYBER.039", Domain: "CYBER", Title: "Sicherheits-Audit OT abgeschlossen", Description: "OT-spezifisches Sicherheits-Audit durch qualifizierte Auditoren wurde durchgefuehrt und Befunde behoben.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "configuration_error"}, EvidenceExamples: []string{"OT-Audit-Bericht", "Finding-Closing-Nachweis"}, ReductionType: "design", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.CYBER.040", Domain: "CYBER", Title: "Cyber-Resilience-Plan vorhanden", Description: "Ein Cyber-Resilience-Plan definiert Massnahmen fuer den Weiterbetrieb und die schnelle Wiederherstellung nach Cyberangriffen.", PriorityHint: "medium", MapsToHazardCategories: []string{"unauthorized_access", "communication_failure"}, EvidenceExamples: []string{"Resilience-Plan", "BCP-Dokument"}, ReductionType: "protective", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
// ── Domain DOC (Documentation & CE-Akte) ──────────────────────────────
{ID: "CTRL.DOC.001", Domain: "DOC", Title: "Risikobewertung dokumentiert", Description: "Die vollstaendige Risikobewertung inkl. Risikomatrix, Massnahmen und Restrisiken ist dokumentiert und freigegeben.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "software_fault", "mechanical_hazard", "electrical_hazard"}, EvidenceExamples: []string{"Risikobewertungs-Dokument", "Freigabeprotokoll"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.002", Domain: "DOC", Title: "Technical-File vollstaendig", Description: "Das Technical File (Technische Dokumentation) fuer die CE-Kennzeichnung ist vollstaendig und aktuell.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "software_fault", "electrical_hazard"}, EvidenceExamples: []string{"Technical-File-Checkliste", "CE-Dossier"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.003", Domain: "DOC", Title: "Konformitaetserklaerung erstellt", Description: "Die EU-Konformitaetserklaerung (DoC) wurde erstellt, unterzeichnet und liegt dem Produkt bei.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"EU-Konformitaetserklaerung", "CE-Kennzeichen-Nachweis"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.004", Domain: "DOC", Title: "Betriebsanleitung verfasst", Description: "Eine vollstaendige Betriebsanleitung in der Landessprache des Anwenders liegt vor und deckt alle Betriebsmodi ab.", PriorityHint: "critical", MapsToHazardCategories: []string{"hmi_error", "maintenance_hazard", "safety_function_failure"}, EvidenceExamples: []string{"Betriebsanleitung", "Sprachversionen-Nachweis"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.005", Domain: "DOC", Title: "Wartungsanleitung vorhanden", Description: "Eine vollstaendige Wartungsanleitung mit Wartungsintervallen, Ersatzteilen und Pruefanweisungen liegt vor.", PriorityHint: "critical", MapsToHazardCategories: []string{"maintenance_hazard"}, EvidenceExamples: []string{"Wartungsanleitung", "Wartungsintervall-Tabelle"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.006", Domain: "DOC", Title: "Installationsanleitung vorhanden", Description: "Eine vollstaendige Installationsanleitung mit Sicherheitshinweisen und Pruefanweisungen fuer die Inbetriebnahme liegt vor.", PriorityHint: "critical", MapsToHazardCategories: []string{"integration_error", "safety_function_failure"}, EvidenceExamples: []string{"Installationsanleitung", "Inbetriebnahme-Checkliste"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.007", Domain: "DOC", Title: "Sicherheitsdatenblatt vorhanden", Description: "Ein Sicherheitsdatenblatt mit relevanten Sicherheitsinformationen liegt vor und ist aktuell.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "electrical_hazard", "thermal_hazard"}, EvidenceExamples: []string{"Sicherheitsdatenblatt", "REACH-Konformitaet"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.008", Domain: "DOC", Title: "Sicherheitsfunktions-Beschreibung vorhanden", Description: "Alle Sicherheitsfunktionen sind vollstaendig beschrieben inkl. Funktionsprinzip, Ausloesekriterien und Wirkung.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Sicherheitsfunktions-Beschreibung", "Funktionale-Sicherheits-Konzept"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.DOC.009", Domain: "DOC", Title: "CE-Kennzeichnung angebracht", Description: "Das CE-Kennzeichen ist am Produkt angebracht und die zugehoerige Doku ist vollstaendig.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"CE-Kennzeichen-Foto", "Konformitaetserklaerung"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.010", Domain: "DOC", Title: "Pruefberichte archiviert", Description: "Alle Pruef- und Testberichte sind vollstaendig archiviert und fuer 10 Jahre verfuegbar.", PriorityHint: "critical", MapsToHazardCategories: []string{"safety_function_failure", "electrical_hazard", "emc_hazard"}, EvidenceExamples: []string{"Archivierungsnachweis", "Dokumentenregister"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.011", Domain: "DOC", Title: "Normenkonformitaetsmatrix erstellt", Description: "Eine Normenkonformitaetsmatrix zeigt fuer jede anwendbare Norm den Konformitaetsnachweis.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Normenmatrix", "Gap-Analyse"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.012", Domain: "DOC", Title: "Aenderungsdokumentation vollstaendig", Description: "Alle Produktaenderungen sind vollstaendig dokumentiert und die Auswirkungen auf die Zertifizierung bewertet.", PriorityHint: "high", MapsToHazardCategories: []string{"configuration_error", "software_fault"}, EvidenceExamples: []string{"Aenderungsprotokoll", "Impact-Analyse"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.013", Domain: "DOC", Title: "Software-Release-Notes vorhanden", Description: "Fuer jedes Software-Release existieren vollstaendige Release-Notes mit Aenderungen, Fixes und Bekannten-Problemen.", PriorityHint: "high", MapsToHazardCategories: []string{"software_fault", "update_failure"}, EvidenceExamples: []string{"Release-Notes", "Changelog"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ai"}},
{ID: "CTRL.DOC.014", Domain: "DOC", Title: "Konfigurationshandbuch erstellt", Description: "Ein vollstaendiges Konfigurationshandbuch mit allen Parametern und deren sicheren Wertebereichen liegt vor.", PriorityHint: "high", MapsToHazardCategories: []string{"configuration_error"}, EvidenceExamples: []string{"Konfigurationshandbuch", "Parameter-Referenz"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.DOC.015", Domain: "DOC", Title: "Schulungsunterlagen vorhanden", Description: "Schulungsunterlagen fuer Bediener, Instandhalter und Administratoren sind vorhanden und aktuell.", PriorityHint: "high", MapsToHazardCategories: []string{"hmi_error", "maintenance_hazard"}, EvidenceExamples: []string{"Schulungsunterlagen", "Kompetenzmatrix"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.016", Domain: "DOC", Title: "Lagerungsanweisung vorhanden", Description: "Eine Lagerungsanweisung mit Bedingungen und Hoechstlagerdauer liegt vor.", PriorityHint: "high", MapsToHazardCategories: []string{"environmental_hazard"}, EvidenceExamples: []string{"Lagerungsanweisung", "Verpackungsvorschrift"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.017", Domain: "DOC", Title: "Entsorgungshinweise vorhanden", Description: "Hinweise zur umweltgerechten Entsorgung (WEEE, RoHS) sind im Produkt dokumentiert.", PriorityHint: "high", MapsToHazardCategories: []string{"environmental_hazard"}, EvidenceExamples: []string{"Entsorgungshinweis", "WEEE-Konformitaetsnachweis"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.018", Domain: "DOC", Title: "HARA-Dokumentation vollstaendig", Description: "Die HARA-Dokumentation ist vollstaendig, durch Review freigegeben und alle Massnahmen sind rueckverfolgbar.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure", "mechanical_hazard", "electrical_hazard"}, EvidenceExamples: []string{"HARA-Dokument", "Review-Protokoll"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.019", Domain: "DOC", Title: "SIL-Nachweisdokumentation vollstaendig", Description: "Die vollstaendige SIL-Nachweisdokumentation gemaess IEC 61508 ist vorhanden und durch Zertifizierungsstelle anerkannt.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"SIL-Zertifikat", "Nachweisdokumentation"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl"}},
{ID: "CTRL.DOC.020", Domain: "DOC", Title: "Baumustererpruefung durchgefuehrt", Description: "Eine Baumustererpruefung durch eine notifizierte Stelle wurde durchgefuehrt und ein Zertifikat ausgestellt.", PriorityHint: "high", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Baumustererpruefungs-Zertifikat", "Pruefbericht"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.021", Domain: "DOC", Title: "Erstinbetriebnahme-Protokoll vorhanden", Description: "Ein Erstinbetriebnahme-Protokoll dokumentiert alle Pruefschritte und deren Ergebnisse.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "integration_error"}, EvidenceExamples: []string{"Inbetriebnahme-Protokoll", "Abnahme-Checkliste"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.022", Domain: "DOC", Title: "Wartungsprotokoll gefuehrt", Description: "Wartungsprotokolle werden bei jeder Wartung erstellt und archiviert.", PriorityHint: "medium", MapsToHazardCategories: []string{"maintenance_hazard"}, EvidenceExamples: []string{"Wartungsprotokoll", "Wartungsbuch"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.023", Domain: "DOC", Title: "Kalibrierprotokoll aktuell", Description: "Kalibrierprotokolle fuer alle sicherheitsrelevanten Messgeraete sind aktuell und archiviert.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Kalibrierprotokoll", "Kalibrierzertifikat"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.024", Domain: "DOC", Title: "Vorfallsprotokoll gefuehrt", Description: "Alle Sicherheitsvorfaelle und sicherheitsrelevanten Ereignisse werden protokolliert und ausgewertet.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "software_fault"}, EvidenceExamples: []string{"Vorfallsprotokoll", "Root-Cause-Analyse"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.025", Domain: "DOC", Title: "Audits und Zertifikate archiviert", Description: "Alle Audit-Berichte und Zertifikate sind vollstaendig archiviert und fuer die vorgeschriebene Dauer verfuegbar.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure"}, EvidenceExamples: []string{"Zertifikate-Register", "Archivierungsnachweis"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.026", Domain: "DOC", Title: "Zulieferer-Dokumentation vorhanden", Description: "Alle relevanten Zulieferer-Dokumentationen (Datenblatt, Zertifikat, Konformitaetserklaerung) sind vorhanden.", PriorityHint: "medium", MapsToHazardCategories: []string{"software_fault", "electrical_hazard"}, EvidenceExamples: []string{"Zulieferer-Dokumentenregister", "Komponentenzertifikate"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.027", Domain: "DOC", Title: "Lebenszyklusplan dokumentiert", Description: "Der Produktlebenszyklusplan von Entwicklung bis Ausserbetriebnahme ist dokumentiert und verbindlich.", PriorityHint: "medium", MapsToHazardCategories: []string{"maintenance_hazard", "update_failure"}, EvidenceExamples: []string{"Lebenszyklusplan", "EOL-Strategie"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.028", Domain: "DOC", Title: "Obsoleszenz-Management dokumentiert", Description: "Ein Obsoleszenz-Management-Plan identifiziert Risiken durch auslaufende Komponenten und definiert Massnahmen.", PriorityHint: "medium", MapsToHazardCategories: []string{"update_failure", "software_fault"}, EvidenceExamples: []string{"Obsoleszenz-Plan", "Risiko-Register"}, ReductionType: "information", Applicable: []string{"fw", "ctrl"}},
{ID: "CTRL.DOC.029", Domain: "DOC", Title: "Schnittstellendokumentation vollstaendig", Description: "Alle Systemschnittstellen sind vollstaendig dokumentiert inkl. Protokolle, Datenformate und Fehlercodes.", PriorityHint: "medium", MapsToHazardCategories: []string{"integration_error", "communication_failure"}, EvidenceExamples: []string{"Schnittstellendokumentation", "API-Referenz"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
{ID: "CTRL.DOC.030", Domain: "DOC", Title: "Post-Market-Surveillance-Plan vorhanden", Description: "Ein Post-Market-Surveillance-Plan definiert wie Felddaten, Vorfaelle und Kundenrueckmeldungen systematisch ausgewertet werden.", PriorityHint: "medium", MapsToHazardCategories: []string{"safety_function_failure", "software_fault"}, EvidenceExamples: []string{"PMS-Plan", "PMSR-Bericht"}, ReductionType: "information", Applicable: []string{"sw", "fw", "ctrl", "ai"}},
}
}
// GetProtectiveMeasureLibrary returns the complete built-in protective measures library
// with 160 entries organized by reduction type (design, protection, information)
// following the ISO 12100 three-step method for risk reduction.
//
// Each entry is categorized by sub-type and hazard category, with German-language
// names, descriptions, and practical examples for industrial machinery safety.
func GetProtectiveMeasureLibrary() []ProtectiveMeasureEntry {
return []ProtectiveMeasureEntry{
// ====================================================================
// Type 1: Design (ReductionType: "design") — Inhaerent sichere Konstruktion
// 50 entries: M001-M050
// ====================================================================
{ID: "M001", ReductionType: "design", SubType: "geometry", Name: "Gefahrstelle konstruktiv eliminieren", Description: "Durch konstruktive Gestaltung wird die Gefahrstelle vollstaendig beseitigt, sodass eine Gefaehrdung gar nicht erst entstehen kann.", HazardCategory: "mechanical", Examples: []string{"Quetschstelle durch Geometrieaenderung entfernen", "Einzugsstelle durch vergroesserten Spalt eliminieren", "Scherstelle durch Kinematikanpassung vermeiden"}},
{ID: "M002", ReductionType: "design", SubType: "force_energy", Name: "Bewegungsenergie reduzieren", Description: "Die kinetische Energie beweglicher Maschinenteile wird durch konstruktive Massnahmen auf ein sicheres Niveau begrenzt.", HazardCategory: "mechanical", Examples: []string{"Masse beweglicher Teile verringern", "Hublaenge verkuerzen", "Traegheitsmoment durch Leichtbau reduzieren"}},
{ID: "M003", ReductionType: "design", SubType: "force_energy", Name: "Geschwindigkeit reduzieren", Description: "Die Verfahrgeschwindigkeit wird konstruktiv auf ein Niveau begrenzt, bei dem keine gefaehrlichen Verletzungen auftreten koennen.", HazardCategory: "mechanical", Examples: []string{"Maximale Achsgeschwindigkeit mechanisch begrenzen", "Getriebeuebersetzung anpassen", "Drehzahlbegrenzer einbauen"}},
{ID: "M004", ReductionType: "design", SubType: "force_energy", Name: "Kraft begrenzen", Description: "Die maximal auftretende Kraft wird durch die Konstruktion so weit begrenzt, dass keine gefaehrlichen Verletzungen moeglich sind.", HazardCategory: "mechanical", Examples: []string{"Federbelastete Kraftbegrenzung einsetzen", "Antriebsdrehmoment begrenzen", "Nachgiebige Elemente verwenden"}},
{ID: "M005", ReductionType: "design", SubType: "geometry", Name: "Sicherheitsabstaende vergroessern", Description: "Konstruktive Abstaende zwischen Gefahrstellen und zugaenglichen Bereichen werden so dimensioniert, dass ein Erreichen der Gefahrstelle ausgeschlossen ist.", HazardCategory: "mechanical", Examples: []string{"Greifabstand an Walzen vergroessern", "Abstand zu heissen Oberflaechen erhoehen", "Sicherheitsabstand an Pressen einhalten"}},
{ID: "M006", ReductionType: "design", SubType: "force_energy", Name: "Kinematik aendern", Description: "Die Bewegungsart oder Bewegungsrichtung wird so umgestaltet, dass die Gefaehrdung durch die Maschinenbewegung entfaellt.", HazardCategory: "mechanical", Examples: []string{"Linearbewegung statt Rotation einsetzen", "Bewegungsrichtung von Bedienerseite wegfuehren", "Parallele statt gegenlaefige Walzen verwenden"}},
{ID: "M007", ReductionType: "design", SubType: "geometry", Name: "Rotationsbewegung vermeiden", Description: "Rotierende Teile werden durch alternative Konstruktionsloesungen ersetzt, um Einzugs- und Wickelgefaehrdungen zu beseitigen.", HazardCategory: "mechanical", Examples: []string{"Linearantrieb statt Drehantrieb verwenden", "Riemenantrieb durch Zahnstange ersetzen", "Drehbewegung kapseln"}},
{ID: "M008", ReductionType: "design", SubType: "geometry", Name: "Scharfe Kanten entfernen", Description: "Alle zugaenglichen Kanten und Ecken werden abgerundet oder entgratet, um Schnitt- und Stichverletzungen auszuschliessen.", HazardCategory: "mechanical", Examples: []string{"Radien an Blechkanten anbringen", "Entgratung aller Stanzteile sicherstellen", "Abgerundete Gehaeusekanten vorsehen"}},
{ID: "M009", ReductionType: "design", SubType: "material", Name: "Sichere Materialwahl", Description: "Die verwendeten Werkstoffe werden so gewaehlt, dass sie keine zusaetzlichen Gefaehrdungen verursachen und den Betriebsbelastungen standhalten.", HazardCategory: "material_environmental", Examples: []string{"Nicht-toxische Kunststoffe waehlen", "Korrosionsbestaendige Legierungen einsetzen", "Feuerfeste Materialien an heissen Stellen verwenden"}},
{ID: "M010", ReductionType: "design", SubType: "force_energy", Name: "Gewicht reduzieren", Description: "Das Gewicht beweglicher Maschinenteile wird minimiert, um die potenzielle Verletzungsschwere bei Kollisionen zu verringern.", HazardCategory: "mechanical", Examples: []string{"Leichtbauwerkstoffe fuer bewegliche Arme einsetzen", "Hohlprofile statt Vollmaterial verwenden", "Gegengewichte durch Ausgleichsfedern ersetzen"}},
{ID: "M011", ReductionType: "design", SubType: "force_energy", Name: "Redundante Konstruktion", Description: "Sicherheitskritische Bauteile werden mehrfach ausgefuehrt, sodass beim Versagen einer Komponente die Sicherheitsfunktion erhalten bleibt.", HazardCategory: "mechanical", Examples: []string{"Doppelte Tragseile an Hebezeugen", "Zweifache Verriegelungsmechanismen", "Redundante Bremssysteme vorsehen"}},
{ID: "M012", ReductionType: "design", SubType: "force_energy", Name: "Mechanische Begrenzung", Description: "Feste mechanische Anschlaege oder Endlagen begrenzen den Bewegungsbereich und verhindern ein Ueberfahren sicherheitskritischer Positionen.", HazardCategory: "mechanical", Examples: []string{"Feste Endanschlaege an Linearachsen", "Mechanische Hublimitierung an Pressen", "Drehwinkelbegrenzung an Drehachsen"}},
{ID: "M013", ReductionType: "design", SubType: "geometry", Name: "Sichere Geometrie", Description: "Die Bauteilgeometrie wird so gestaltet, dass Quetsch-, Scher- und Einzugsstellen vermieden werden.", HazardCategory: "mechanical", Examples: []string{"Abgerundete Formteile anstelle scharfkantiger verwenden", "Spaltmasse an Fuehrungen einhalten", "Konische statt zylindrische Aufnahmen waehlen"}},
{ID: "M014", ReductionType: "design", SubType: "material", Name: "Stabile Konstruktion", Description: "Die Konstruktion wird auf ausreichende Festigkeit und Stabilitaet ausgelegt, um ein strukturelles Versagen unter allen Betriebsbedingungen zu verhindern.", HazardCategory: "mechanical", Examples: []string{"Sicherheitsfaktoren bei Tragstrukturen einhalten", "Kippstabilitaet rechnerisch nachweisen", "Dauerfestigkeit der Schweissnaehte pruefen"}},
{ID: "M015", ReductionType: "design", SubType: "geometry", Name: "Kollisionsfreie Bewegungsbahnen", Description: "Die Bewegungsbahnen werden so geplant, dass Kollisionen mit Personen oder Gegenstaenden konstruktiv ausgeschlossen sind.", HazardCategory: "mechanical", Examples: []string{"Verfahrwege ausserhalb des Bedienerbereichs legen", "Ueberlappungsfreie Arbeitsbereiche definieren", "Bewegungsbahnen in der Simulation pruefen"}},
{ID: "M016", ReductionType: "design", SubType: "geometry", Name: "Sichere Greifer", Description: "Greifersysteme werden so konstruiert, dass ein unkontrolliertes Freisetzen des Werkstuecks und Quetschungen ausgeschlossen sind.", HazardCategory: "mechanical", Examples: []string{"Formschluessige Greiferbacken verwenden", "Federbelastete Greifer fuer Fail-Safe-Zustand", "Weiche Greiferbacken fuer empfindliche Teile"}},
{ID: "M017", ReductionType: "design", SubType: "geometry", Name: "Sichere Halterungen", Description: "Halterungen und Befestigungen sind so konstruiert, dass ein unbeabsichtigtes Loesen auch unter dynamischen Belastungen ausgeschlossen ist.", HazardCategory: "mechanical", Examples: []string{"Selbstsichernde Muttern verwenden", "Formschluessige Klemmverbindungen einsetzen", "Sicherungsstifte an Bolzenverbindungen vorsehen"}},
{ID: "M018", ReductionType: "design", SubType: "geometry", Name: "Sichere Werkstueckaufnahme", Description: "Werkstueckaufnahmen werden so gestaltet, dass ein Herausschleudern des Werkstuecks bei allen Betriebszustaenden verhindert wird.", HazardCategory: "mechanical", Examples: []string{"Spannvorrichtung mit Formschluss ausstatten", "Automatische Spannkontrolle integrieren", "Niederzugspanner an Fraestischen verwenden"}},
{ID: "M019", ReductionType: "design", SubType: "geometry", Name: "Sichere Lagefuehrung", Description: "Fuehrungselemente stellen sicher, dass sich bewegliche Teile nur in der vorgesehenen Bahn bewegen und kein seitliches Ausbrechen moeglich ist.", HazardCategory: "mechanical", Examples: []string{"Praezise Linearfuehrungen mit Spielausgleich", "Kugelfuehrungen fuer spielfreie Bewegung", "Gleitfuehrungen mit Anschlag"}},
{ID: "M020", ReductionType: "design", SubType: "geometry", Name: "Sichere Lastfuehrung", Description: "Das Fuehrungssystem fuer Lasten ist so dimensioniert, dass ein unkontrolliertes Herabfallen oder Abrutschen der Last verhindert wird.", HazardCategory: "mechanical", Examples: []string{"Fangvorrichtung an Hubtischen einbauen", "Kettensperre bei Kettenfoerderern vorsehen", "Lasthalteventile in Hubzylindern verwenden"}},
{ID: "M021", ReductionType: "design", SubType: "geometry", Name: "Sichere Kraftuebertragung", Description: "Kraftuebertragungselemente sind so dimensioniert und gesichert, dass ein Bruch oder Loesen keine Gefaehrdung verursacht.", HazardCategory: "mechanical", Examples: []string{"Wellensicherungen gegen Axialverschiebung", "Bruchsichere Kupplungen dimensionieren", "Sicherheitswellen mit Sollbruchstelle verwenden"}},
{ID: "M022", ReductionType: "design", SubType: "force_energy", Name: "Sichere Energieuebertragung", Description: "Energieleitungen und -uebertragungselemente werden so verlegt und dimensioniert, dass Leckagen oder Brueche keine Gefaehrdung darstellen.", HazardCategory: "electrical", Examples: []string{"Schleppketten fuer flexible Leitungen einsetzen", "Zugentlastungen an Steckverbindungen anbringen", "Doppelwandige Druckleitungen verwenden"}},
{ID: "M023", ReductionType: "design", SubType: "fluid_design", Name: "Sichere Hydraulikdimensionierung", Description: "Das Hydrauliksystem wird so ausgelegt, dass Druckspitzen und Leitungsbrueche keine unkontrollierten Bewegungen verursachen.", HazardCategory: "pneumatic_hydraulic", Examples: []string{"Druckspeicher mit Berstscheibe absichern", "Schlauchbruchsicherungen einbauen", "Hydraulikleitungen druckfest dimensionieren"}},
{ID: "M024", ReductionType: "design", SubType: "fluid_design", Name: "Sichere Pneumatikdimensionierung", Description: "Pneumatische Systeme werden so ausgelegt, dass ein Druckverlust oder Leitungsbruch zu einem sicheren Zustand fuehrt.", HazardCategory: "pneumatic_hydraulic", Examples: []string{"Federrueckstellung bei Druckausfall vorsehen", "Druckbegrenzer in Versorgungsleitungen einbauen", "Auffangbehaelter fuer Kondensat installieren"}},
{ID: "M025", ReductionType: "design", SubType: "fluid_design", Name: "Sichere thermische Auslegung", Description: "Die thermische Belastung aller Komponenten wird bei der Konstruktion beruecksichtigt, um Ueberhitzung und Brandgefahr zu vermeiden.", HazardCategory: "thermal", Examples: []string{"Waermeableitung durch Kuehlrippen sicherstellen", "Thermisch belastete Bauteile mit Sicherheitsreserve auslegen", "Brandlast durch Materialwahl minimieren"}},
{ID: "M026", ReductionType: "design", SubType: "fluid_design", Name: "Temperaturbegrenzung", Description: "Durch konstruktive Massnahmen wird sichergestellt, dass zugaengliche Oberflaechen keine gefaehrlichen Temperaturen erreichen.", HazardCategory: "thermal", Examples: []string{"Isolierungen an heissen Rohrleitungen anbringen", "Thermische Abschirmungen an Oefen vorsehen", "Oberflaechentemperatur unter 43 Grad Celsius halten"}},
{ID: "M027", ReductionType: "design", SubType: "fluid_design", Name: "Passive Kuehlung", Description: "Waerme wird ohne aktive Komponenten abgefuehrt, sodass kein Ausfall der Kuehlung zu einer Ueberhitzung fuehren kann.", HazardCategory: "thermal", Examples: []string{"Natuerliche Konvektion durch Rippendesign foerdern", "Waermeleitrohre (Heatpipes) einsetzen", "Waermeableitung ueber Maschinengestell realisieren"}},
{ID: "M028", ReductionType: "design", SubType: "fluid_design", Name: "Automatische Druckbegrenzung", Description: "Druckbehaelter und -leitungen sind mit passiven Begrenzungselementen ausgestattet, die ein Ueberschreiten des zulaessigen Drucks verhindern.", HazardCategory: "pneumatic_hydraulic", Examples: []string{"Berstscheiben an Druckbehaeltern montieren", "Ueberdruckventile in Hydraulikkreisen integrieren", "Druckabsicherung in Pneumatikleitungen vorsehen"}},
{ID: "M029", ReductionType: "design", SubType: "geometry", Name: "Sichere Sensorposition", Description: "Sensoren werden so positioniert, dass sie zuverlaessig messen und gleichzeitig vor mechanischer Beschaedigung geschuetzt sind.", HazardCategory: "software_control", Examples: []string{"Sensoren in geschuetzten Nischen montieren", "Abgeschirmte Sensorgehaeuse verwenden", "Sensoren ausserhalb des Gefahrbereichs platzieren"}},
{ID: "M030", ReductionType: "design", SubType: "geometry", Name: "Sichere Kabelfuehrung", Description: "Elektrische Leitungen werden so gefuehrt, dass sie vor mechanischer Beschaedigung, Feuchtigkeit und Hitze geschuetzt sind.", HazardCategory: "electrical", Examples: []string{"Kabelkanaele mit Deckel verwenden", "Leitungen in Schleppketten fuehren", "Kabel mit Knickschutz an Durchfuehrungen versehen"}},
{ID: "M031", ReductionType: "design", SubType: "geometry", Name: "Sichere Leitungsfuehrung", Description: "Hydraulik- und Pneumatikleitungen werden so verlegt, dass sie vor Beschaedigung geschuetzt sind und Leckagen erkannt werden koennen.", HazardCategory: "pneumatic_hydraulic", Examples: []string{"Leitungen in geschuetzten Kanaelen verlegen", "Auffangwannen unter Hydraulikleitungen montieren", "Farbcodierte Leitungen fuer schnelle Identifikation"}},
{ID: "M032", ReductionType: "design", SubType: "noise_vibration", Name: "Vibrationsarme Konstruktion", Description: "Durch konstruktive Massnahmen werden Vibrationen und Koerperschall an der Quelle minimiert.", HazardCategory: "noise_vibration", Examples: []string{"Schwingungsdaempfer an Motoren einbauen", "Unwuchtfreie Rotoren konstruieren", "Elastische Maschinenlagerung vorsehen"}},
{ID: "M033", ReductionType: "design", SubType: "ergonomics", Name: "Ergonomische Gestaltung", Description: "Die Maschine wird so gestaltet, dass eine koerperlich belastungsarme und gesundheitsschonende Bedienung moeglich ist.", HazardCategory: "ergonomic", Examples: []string{"Arbeitshoehe an Bedienergroesse anpassbar machen", "Gewicht von Handwerkzeugen unter 2,5 kg halten", "Griffgestaltung nach ergonomischen Richtlinien"}},
{ID: "M034", ReductionType: "design", SubType: "ergonomics", Name: "Gute Sichtbarkeit", Description: "Alle sicherheitsrelevanten Bereiche sind vom Bedienstandort aus gut einsehbar, damit Gefaehrdungen rechtzeitig erkannt werden.", HazardCategory: "ergonomic", Examples: []string{"Transparente Schutzhauben verwenden", "Spiegel an unuebersichtlichen Stellen montieren", "Kamerabasierte Sichthilfen installieren"}},
{ID: "M035", ReductionType: "design", SubType: "ergonomics", Name: "Intuitive Bedienoberflaeche", Description: "Bedienelemente und Anzeigen sind so gestaltet, dass Fehlbedienungen durch unklare Zuordnung vermieden werden.", HazardCategory: "ergonomic", Examples: []string{"Einheitliche Farbcodierung fuer Bedienfunktionen", "Logische Anordnung der Bedienelemente", "Beschriftung in Landessprache und mit Piktogrammen"}},
{ID: "M036", ReductionType: "design", SubType: "ergonomics", Name: "Sichere Mensch-Maschine-Interaktion", Description: "Die Schnittstelle zwischen Bediener und Maschine ist so konzipiert, dass gefaehrliche Missverstaendnisse ausgeschlossen sind.", HazardCategory: "ergonomic", Examples: []string{"Eindeutige Statusindikatoren an der Maschine anbringen", "Akustische und optische Rueckmeldung bei Gefahrsituationen", "Bestaetigung vor Ausfuehrung kritischer Befehle fordern"}},
{ID: "M037", ReductionType: "design", SubType: "ergonomics", Name: "Sichere Bedienhoehe", Description: "Bedienelemente sind in einer Hoehe angebracht, die ein sicheres und ermuedungsfreies Arbeiten ermoeglicht.", HazardCategory: "ergonomic", Examples: []string{"Hauptbedienfeld auf Ellbogenhoehe montieren", "Not-Halt in Greifhoehe anbringen", "Schwenkbare Bedientableaus fuer flexible Positionierung"}},
{ID: "M038", ReductionType: "design", SubType: "ergonomics", Name: "Sichere Reichweiten", Description: "Alle sicherheitsrelevanten Bedienelemente befinden sich innerhalb der ergonomisch guenstigen Reichweite des Bedieners.", HazardCategory: "ergonomic", Examples: []string{"Haeufig genutzte Taster im Nahbereich anordnen", "Selten genutzte Schalter im Fernbereich platzieren", "Reichweitendiagramme bei der Planung anwenden"}},
{ID: "M039", ReductionType: "design", SubType: "ergonomics", Name: "Sichere Wartungszugaenge", Description: "Wartungsbereiche sind so gestaltet, dass Wartungsarbeiten gefahrlos und ohne Demontage sicherheitsrelevanter Schutzeinrichtungen durchgefuehrt werden koennen.", HazardCategory: "ergonomic", Examples: []string{"Wartungsklappen mit Sicherheitsverriegelung vorsehen", "Inspektionsoeffnungen an kritischen Stellen anbringen", "Ausreichende Arbeitsflaeche im Wartungsbereich sicherstellen"}},
{ID: "M040", ReductionType: "design", SubType: "ergonomics", Name: "Sichere Montagepunkte", Description: "Montagepunkte fuer Baugruppen sind so konstruiert, dass ein sicheres Handling waehrend Montage und Demontage gewaehrleistet ist.", HazardCategory: "ergonomic", Examples: []string{"Anschlagpunkte fuer Hebezeuge vorsehen", "Passstifte fuer lagegenaue Montage verwenden", "Montagehilfen fuer schwere Baugruppen bereitstellen"}},
{ID: "M041", ReductionType: "design", SubType: "ergonomics", Name: "Sichere Demontagepunkte", Description: "Demontagepunkte sind so markiert und konstruiert, dass ein sicherer Rueckbau ohne unbeabsichtigtes Freisetzen von Energie moeglich ist.", HazardCategory: "ergonomic", Examples: []string{"Ablassoeffnungen fuer Betriebsfluide vorsehen", "Entlueftungspunkte fuer Druckbehaelter kennzeichnen", "Abziehgewinde fuer Pressverbindungen einplanen"}},
{ID: "M042", ReductionType: "design", SubType: "ergonomics", Name: "Sichere Servicezugaenge", Description: "Servicebereiche sind bei abgeschalteter Maschine sicher zugaenglich und alle gespeicherten Energien koennen kontrolliert abgebaut werden.", HazardCategory: "ergonomic", Examples: []string{"Servicetreppen und -plattformen montieren", "Beleuchtung im Servicebereich installieren", "Ableitungsmechanismen fuer gespeicherte Energie bereitstellen"}},
{ID: "M043", ReductionType: "design", SubType: "control_design", Name: "Sichere Software-Fallbacks", Description: "Die Steuerungssoftware enthaelt definierte Rueckfallstrategien, die bei Softwarefehlern einen sicheren Maschinenzustand herstellen.", HazardCategory: "software_control", Examples: []string{"Standardwerte bei Sensorausfall verwenden", "Sicherer Stopp bei unplausiblen Eingangsdaten", "Automatischer Wechsel in den Notbetrieb bei Softwarefehler"}},
{ID: "M044", ReductionType: "design", SubType: "control_design", Name: "Deterministische Steuerungslogik", Description: "Die Steuerungslogik ist vollstaendig deterministisch aufgebaut, sodass bei identischen Eingaben immer identische Ausgaben erzeugt werden.", HazardCategory: "software_control", Examples: []string{"Keine Zufallselemente in Sicherheitsfunktionen verwenden", "Feste Zykluszeiten fuer alle sicherheitsrelevanten Tasks", "Deadlock-freie Programmstruktur sicherstellen"}},
{ID: "M045", ReductionType: "design", SubType: "control_design", Name: "Definierte Zustandsmaschine", Description: "Alle Maschinenzustaende und Uebergaenge sind vollstaendig definiert, dokumentiert und gegen unzulaessige Zustandswechsel abgesichert.", HazardCategory: "software_control", Examples: []string{"Zustandsdiagramm fuer alle Betriebsmodi erstellen", "Ungueltige Zustandsuebergaenge softwareseitig blockieren", "Maschinenzustand dauerhaft anzeigen"}},
{ID: "M046", ReductionType: "design", SubType: "control_design", Name: "Sichere Restart-Logik", Description: "Ein Neustart der Maschine nach Stopp oder Fehler ist nur durch bewusste Bedienerhandlung moeglich und fuehrt in einen sicheren Ausgangszustand.", HazardCategory: "software_control", Examples: []string{"Automatischen Wiederanlauf nach Netzausfall verhindern", "Quittierungspflicht vor Neustart einbauen", "Schrittweisen Anlauf nach Fehler erzwingen"}},
{ID: "M047", ReductionType: "design", SubType: "control_design", Name: "Sichere Fehlermodi", Description: "Jeder erkannte Fehler fuehrt die Maschine in einen vordefinierten sicheren Zustand, ohne dass eine Bedienerinteraktion erforderlich ist.", HazardCategory: "software_control", Examples: []string{"Fail-Safe-Verhalten bei Sensorausfall implementieren", "Fail-Stop bei unbekanntem Fehlerzustand", "Fehlerkatalog mit zugeordneten sicheren Zustaenden pflegen"}},
{ID: "M048", ReductionType: "design", SubType: "control_design", Name: "Sichere Energieabschaltung", Description: "Die Maschine kann jederzeit sicher und vollstaendig von allen Energiequellen getrennt werden.", HazardCategory: "electrical", Examples: []string{"Hauptschalter mit Absperrmoeglichkeit vorsehen", "Pneumatik-Absperrventil am Maschineneingang installieren", "Alle Energiequellen mit eindeutiger Beschriftung versehen"}},
{ID: "M049", ReductionType: "design", SubType: "control_design", Name: "Sichere Energieentladung", Description: "Nach dem Abschalten werden alle gespeicherten Energien kontrolliert abgebaut, bevor der Zugang zum Gefahrbereich freigegeben wird.", HazardCategory: "electrical", Examples: []string{"Kondensatoren ueber Entladewiderstaende entladen", "Druckspeicher ueber Entlastungsventil entspannen", "Federspeicher kontrolliert loesen"}},
{ID: "M050", ReductionType: "design", SubType: "control_design", Name: "Sichere Notzustaende", Description: "Fuer alle vorhersehbaren Notsituationen sind definierte Zustaende festgelegt, die automatisch oder durch Bedienereingriff hergestellt werden.", HazardCategory: "general", Examples: []string{"Not-Halt-Zustand mit definierten Achspositionen", "Notzustand bei Brand mit automatischer Loeschausloesung", "Evakuierungszustand mit geoeffneten Schutztoren"}},
// ====================================================================
// Type 2: Protection (ReductionType: "protection") — Technische Schutzmassnahmen
// 70 entries: M051-M120
// ====================================================================
{ID: "M051", ReductionType: "protection", SubType: "fixed_guard", Name: "Feste trennende Schutzeinrichtung", Description: "Eine fest montierte physische Barriere verhindert den Zugang zum Gefahrbereich und kann nur mit Werkzeug entfernt werden.", HazardCategory: "mechanical", Examples: []string{"Verschraubte Schutzverkleidung an Antrieben", "Fest montierter Schutzzaun um Roboterzelle", "Schutzhaube ueber Riementrieb"}},
{ID: "M052", ReductionType: "protection", SubType: "movable_guard", Name: "Bewegliche Schutzeinrichtung", Description: "Eine bewegliche Schutzeinrichtung kann ohne Werkzeug geoeffnet werden und ist mit einer Verriegelung gekoppelt, die die Maschine bei geoeffneter Tuer abschaltet.", HazardCategory: "mechanical", Examples: []string{"Schwenkbare Schutzhaube mit Sicherheitsschalter", "Schiebetueren mit Verriegelungssystem", "Klappbare Schutzabdeckung mit Positionsschalter"}},
{ID: "M053", ReductionType: "protection", SubType: "movable_guard", Name: "Verriegelte Schutztuer", Description: "Die Schutztuer ist mit einer Sicherheitsverriegelung versehen, die ein Oeffnen nur bei stillstehender Maschine erlaubt.", HazardCategory: "mechanical", Examples: []string{"Zuhaltung mit Zeitverzoegerung an Schutztuer", "Elektromagnetische Zuhaltung mit Freigabebestaetigung", "Bolzenverriegelung mit sicherer Positionsueberwachung"}},
{ID: "M054", ReductionType: "protection", SubType: "electro_sensitive", Name: "Lichtgitter", Description: "Ein optoelektronisches Schutzfeld erkennt das Eingreifen in den Gefahrbereich und loest einen sicheren Maschinenstopp aus.", HazardCategory: "mechanical", Examples: []string{"Typ-4-Lichtgitter an Pressenzufuehrung", "Handschutz-Lichtgitter mit 14mm Aufloesung", "Koerperschutz-Lichtgitter mit 30mm Aufloesung"}},
{ID: "M055", ReductionType: "protection", SubType: "electro_sensitive", Name: "Laserscanner", Description: "Ein flaechenabdeckendes Laserscansystem ueberwacht den Bodenbereich vor der Maschine und unterscheidet zwischen Warn- und Schutzfeld.", HazardCategory: "mechanical", Examples: []string{"Sicherheitslaserscanner an mobiler Plattform", "Bodennaher Laserscanner an Palettieranlage", "Multizonen-Laserscanner mit anpassbaren Feldern"}},
{ID: "M056", ReductionType: "protection", SubType: "electrical_protection", Name: "Zweihandbedienung", Description: "Die Maschine kann nur ausgeloest werden, wenn beide Haende des Bedieners gleichzeitig an den Bedienelementen sind, sodass sie sich nicht im Gefahrbereich befinden koennen.", HazardCategory: "mechanical", Examples: []string{"Zweihand-Sicherheitsschaltung an Exzenterpresse", "Synchrone Tastenbetaetigung mit Zeitfenster unter 0,5s", "Typ-IIIC-Zweihandsteuerung installieren"}},
{ID: "M057", ReductionType: "protection", SubType: "electrical_protection", Name: "Zustimmschalter", Description: "Ein Dreistufenschalter erlaubt das Verfahren der Maschine im Einrichtbetrieb nur solange der Bediener den Taster aktiv gedrueckt haelt.", HazardCategory: "mechanical", Examples: []string{"Dreistufigen Zustimmtaster am Handgeraet verbauen", "Zustimmfunktion fuer Roboter-Teachbetrieb aktivieren", "Panikausloesung bei Durchdruecken oder Loslassen"}},
{ID: "M058", ReductionType: "protection", SubType: "emergency_stop", Name: "Not-Halt", Description: "Rot-gelbe Pilztaster sind an allen Bedienstellen und Zugaengen angebracht und fuehren die Maschine in den sicheren Stopp-Zustand.", HazardCategory: "general", Examples: []string{"Not-Halt-Taster an jedem Bedienfeld montieren", "Not-Halt-Reissleine entlang langer Foerderstrecken", "Drahtlos verbundenen Not-Halt-Taster fuer mobile Bedienung"}},
{ID: "M059", ReductionType: "protection", SubType: "electrical_protection", Name: "Sicherheitsrelais", Description: "Zwangsgefuehrte Sicherheitsrelais ueberwachen Schutzeinrichtungen und schalten die Maschine bei Ausfall zuverlaessig ab.", HazardCategory: "electrical", Examples: []string{"Not-Halt-Sicherheitsrelais mit Querschlusserkennung", "Tuerverriegelungs-Auswertegeraet installieren", "Lichtgitter-Sicherheitsrelais mit Anlauftestung"}},
{ID: "M060", ReductionType: "protection", SubType: "safety_control", Name: "Sichere SPS", Description: "Eine fehlersichere speicherprogrammierbare Steuerung fuehrt alle sicherheitsrelevanten Funktionen redundant und diversitaer aus.", HazardCategory: "software_control", Examples: []string{"Zweikanalige SPS mit Kreuzvergleich einsetzen", "SIL-3-zertifizierte Safety-SPS installieren", "Sicherheitsprogramm mit Diversitaet ausfuehren"}},
{ID: "M061", ReductionType: "protection", SubType: "safety_control", Name: "Sicherheitssteuerung", Description: "Eine dedizierte Sicherheitssteuerung uebernimmt ausschliesslich die sicherheitsrelevanten Steuerungsfunktionen getrennt von der Standardsteuerung.", HazardCategory: "software_control", Examples: []string{"Separaten Safety-Controller fuer Achsueberwachung einsetzen", "Sicherheitssteuerung mit eigenem Diagnosesystem betreiben", "Safety-Netzwerk von Standard-Netzwerk trennen"}},
{ID: "M062", ReductionType: "protection", SubType: "electrical_protection", Name: "Sichere Positionsueberwachung", Description: "Die Position sicherheitskritischer Achsen wird redundant ueberwacht und bei Abweichung wird ein sicherer Zustand hergestellt.", HazardCategory: "mechanical", Examples: []string{"Doppelte Absolutwertgeber an Servoachsen", "Sichere Positionsauswertung ueber Safety-SPS", "Referenzfahrt mit sicherer Endlageerkennung"}},
{ID: "M063", ReductionType: "protection", SubType: "electrical_protection", Name: "Sichere Geschwindigkeitsueberwachung", Description: "Die Geschwindigkeit beweglicher Maschinenteile wird sicher ueberwacht und bei Ueberschreitung des Grenzwerts wird ein Stopp ausgeloest.", HazardCategory: "mechanical", Examples: []string{"Sichere Drehzahlueberwachung an Spindeln", "Geschwindigkeitsbegrenzung im Einrichtbetrieb ueberwachen", "Zweikanalige Geschwindigkeitsmessung implementieren"}},
{ID: "M064", ReductionType: "protection", SubType: "electrical_protection", Name: "Sichere Stillstandsueberwachung", Description: "Der Stillstand sicherheitskritischer Achsen wird sicher erkannt und der Zugang zum Gefahrbereich erst nach bestaetigtem Stillstand freigegeben.", HazardCategory: "mechanical", Examples: []string{"Sichere Stillstandserkennung ueber Geberrauswertung", "Stillstandsfreigabe fuer Schutztueroeffnung implementieren", "Zeitverzoegerte Freigabe nach Motorabschaltung"}},
{ID: "M065", ReductionType: "protection", SubType: "fluid_protection", Name: "Sicherheitsventil", Description: "Ein Sicherheitsventil oeffnet bei Ueberschreitung des zulaessigen Drucks und leitet das Medium kontrolliert ab.", HazardCategory: "pneumatic_hydraulic", Examples: []string{"Federbelastetes Sicherheitsventil am Druckbehaelter", "Ueberstroemventil in Hydraulikkreislauf einbauen", "Entlueftungsventil bei Pneumatikueberdruck vorsehen"}},
{ID: "M066", ReductionType: "protection", SubType: "fluid_protection", Name: "Druckbegrenzungsventil", Description: "Ein voreingestelltes Druckbegrenzungsventil schuetzt das System vor unzulaessig hohem Druck im gesamten Betriebsbereich.", HazardCategory: "pneumatic_hydraulic", Examples: []string{"Druckbegrenzungsventil in Hydraulik-Hauptleitung", "Reduzierventil in Pneumatik-Zuluftleitung", "Druckwaechterschaltung mit Abschaltung bei Ueberdruck"}},
{ID: "M067", ReductionType: "protection", SubType: "electrical_protection", Name: "Sicherheitskupplung", Description: "Eine Sicherheitskupplung trennt die Kraftuebertragung bei Ueberschreitung des zulaessigen Drehmoments und schuetzt so Mensch und Maschine.", HazardCategory: "mechanical", Examples: []string{"Rutschkupplung in Antriebsstrang einbauen", "Brechbolzenkupplung als Sollbruchstelle vorsehen", "Elektronisch ueberwachte Sicherheitskupplung verwenden"}},
{ID: "M068", ReductionType: "protection", SubType: "electrical_protection", Name: "Mechanischer Anschlag", Description: "Feste Anschlaege begrenzen den Verfahrweg und verhindern ein Ueberfahren der zulaessigen Endposition.", HazardCategory: "mechanical", Examples: []string{"Hartanschlag an Linearachse montieren", "Stossabsorber am Verfahrwegende einbauen", "Anschlagpuffer an Schwenkachse anbringen"}},
{ID: "M069", ReductionType: "protection", SubType: "electrical_protection", Name: "Bremssystem", Description: "Ein zuverlaessiges Bremssystem verzoegert und stoppt bewegliche Maschinenteile bei Abschaltung oder im Notfall.", HazardCategory: "mechanical", Examples: []string{"Federspeicherbremse an Vertikalachse montieren", "Haltebremse an jeder Antriebsachse vorsehen", "Redundante Bremse mit diversitaerem Wirkprinzip einsetzen"}},
{ID: "M070", ReductionType: "protection", SubType: "electrical_protection", Name: "Energieabschaltung", Description: "Die sichere Energieabschaltung trennt die Maschine zuverlaessig von allen Energiequellen und stellt sicher, dass keine Restenergie vorhanden ist.", HazardCategory: "electrical", Examples: []string{"Reparaturschalter mit Vorhangschloss-Absperrung", "Pneumatik-Absperrventil mit Entlueftung", "Hydraulik-Absperrung mit Druckentlastung"}},
{ID: "M071", ReductionType: "protection", SubType: "electrical_protection", Name: "Lockout-Tagout", Description: "Ein definiertes Verfahren zur Verriegelung und Kennzeichnung von Energiequellen stellt sicher, dass waehrend Wartungsarbeiten keine unbeabsichtigte Energiezufuhr erfolgt.", HazardCategory: "electrical", Examples: []string{"Absperrvorrichtungen fuer alle Energiequellen bereitstellen", "Persoenliche Sicherheitsschloesser an jeden Wartungsarbeiter ausgeben", "LOTO-Verfahrensanweisung an der Maschine aushangen"}},
{ID: "M072", ReductionType: "protection", SubType: "safety_control", Name: "Automatische Abschaltung", Description: "Die Maschine wird bei Erkennung eines Fehlers oder einer gefaehrlichen Situation automatisch in den sicheren Zustand gebracht.", HazardCategory: "software_control", Examples: []string{"Automatische Abschaltung bei Uebertemperatur", "Selbsttaetige Stillsetzung bei Schwingungsueberschreitung", "Automatischer Stopp bei Sensorausfall"}},
{ID: "M073", ReductionType: "protection", SubType: "electro_sensitive", Name: "Sicherheitslichtschranke", Description: "Einstrahl-Sicherheitslichtschranken ueberwachen den Zugang zu Gefahrbereichen und loesen bei Unterbrechung einen sicheren Stopp aus.", HazardCategory: "mechanical", Examples: []string{"Einstrahl-Lichtschranke an Maschinenzugang", "Umlenkspiegel-Lichtschranke fuer L-foermigen Bereich", "Reflex-Lichtschranke an Auswurfoeffnung"}},
{ID: "M074", ReductionType: "protection", SubType: "pressure_sensitive", Name: "Sicherheitsmatte", Description: "Druckempfindliche Bodenmatten erkennen das Betreten des Gefahrbereichs und loesen einen sicheren Maschinenstopp aus.", HazardCategory: "mechanical", Examples: []string{"Sicherheitsmatte vor Roboterzelle auslegen", "Schaltmatte unter Palettierstation installieren", "Trittflaeche mit Personenerkennung am Maschinenzugang"}},
{ID: "M075", ReductionType: "protection", SubType: "fixed_guard", Name: "Schutzzaun", Description: "Ein feststehender Schutzzaun umgibt den Gefahrbereich vollstaendig und kann nur mit Werkzeug demontiert werden.", HazardCategory: "mechanical", Examples: []string{"Stahlgitterzaun um Roboterzelle montieren", "Polycarbonat-Schutzwand an Drehmaschine befestigen", "Maschendrahtzaun um Foerderanlage aufstellen"}},
{ID: "M076", ReductionType: "protection", SubType: "movable_guard", Name: "Verriegelungssystem", Description: "Ein kombiniertes Verriegelungs- und Zuhaltesystem stellt sicher, dass Schutztueren nur im sicheren Maschinenzustand geoeffnet werden koennen.", HazardCategory: "mechanical", Examples: []string{"Sicherheits-Tuerschalter mit Zuhaltung montieren", "RFID-basierte Zuhalteeinrichtung einsetzen", "Codierte Sicherheitsschalter mit Manipulationsschutz"}},
{ID: "M077", ReductionType: "protection", SubType: "cybersecurity", Name: "Zugangskontrolle", Description: "Ein physisches oder elektronisches Zugangskontrollsystem stellt sicher, dass nur autorisierte Personen die Maschine bedienen koennen.", HazardCategory: "cyber_network", Examples: []string{"Schluesselsystem fuer Betriebsartenwahl einsetzen", "RFID-Chipkarten fuer Maschinenzugang verwenden", "Biometrische Zugangskontrolle am Schaltschrank"}},
{ID: "M078", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Authentifizierung", Description: "Alle Benutzer muessen sich vor der Nutzung von Steuerungsfunktionen sicher authentifizieren, um unberechtigten Zugriff zu verhindern.", HazardCategory: "cyber_network", Examples: []string{"Passwortschutz am HMI-Panel aktivieren", "Mehrstufige Authentifizierung fuer Parametrierung einrichten", "Zeitlich begrenzte Sitzungen am Bedienterminal"}},
{ID: "M079", ReductionType: "protection", SubType: "cybersecurity", Name: "Rollenbasierte Rechte", Description: "Zugriffsrechte auf Maschinenfunktionen und Parameter sind nach Benutzerrollen differenziert und einschraenkt.", HazardCategory: "cyber_network", Examples: []string{"Bediener-Rolle mit eingeschraenkten Rechten definieren", "Instandhalter-Rolle mit erweitertem Parameterzugriff", "Administrator-Rolle fuer Konfigurationsaenderungen"}},
{ID: "M080", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Netzwerksegmentierung", Description: "Das Maschinennetzwerk ist von anderen Netzwerken getrennt, um ein Uebergreifen von Angriffen auf sicherheitskritische Steuerungen zu verhindern.", HazardCategory: "cyber_network", Examples: []string{"OT-Netzwerk vom IT-Netzwerk per VLAN trennen", "Safety-Netzwerk physisch vom Standard-Netzwerk isolieren", "DMZ zwischen Office- und Produktionsnetzwerk einrichten"}},
{ID: "M081", ReductionType: "protection", SubType: "cybersecurity", Name: "Firewall", Description: "Eine konfigurierte Firewall schuetzt das Steuerungsnetzwerk vor unautorisiertem Netzwerkverkehr.", HazardCategory: "cyber_network", Examples: []string{"Industrie-Firewall vor SPS-Netzwerk installieren", "Deep-Packet-Inspection fuer Industrieprotokolle aktivieren", "Whitelisting fuer erlaubte Kommunikationsverbindungen"}},
{ID: "M082", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Fernwartung", Description: "Der Fernzugriff auf die Maschine erfolgt ausschliesslich ueber verschluesselte und authentifizierte Verbindungen mit zeitlicher Begrenzung.", HazardCategory: "cyber_network", Examples: []string{"VPN-Verbindung fuer Fernwartung einrichten", "Fernzugriff nur nach lokaler Freigabe ermoeglichen", "Session-Timeout fuer Fernwartungszugang konfigurieren"}},
{ID: "M083", ReductionType: "protection", SubType: "cybersecurity", Name: "Verschluesselte Kommunikation", Description: "Alle sicherheitsrelevanten Kommunikationsverbindungen sind verschluesselt, um Abhoeren und Manipulation zu verhindern.", HazardCategory: "cyber_network", Examples: []string{"TLS-Verschluesselung fuer HMI-Kommunikation aktivieren", "OPC UA mit Security Mode Sign&Encrypt konfigurieren", "MQTT-Kommunikation mit TLS absichern"}},
{ID: "M084", ReductionType: "protection", SubType: "cybersecurity", Name: "Signierte Updates", Description: "Software- und Firmware-Updates werden vor der Installation auf ihre Authentizitaet und Integritaet geprueft.", HazardCategory: "cyber_network", Examples: []string{"Code-Signing fuer Steuerungssoftware implementieren", "Firmware-Updates nur mit gueltiger Signatur akzeptieren", "Hash-Pruefung vor jeder Update-Installation durchfuehren"}},
{ID: "M085", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Updatepruefung", Description: "Vor dem Einspielen eines Updates wird automatisch geprueft, ob es mit der bestehenden Konfiguration kompatibel und sicher ist.", HazardCategory: "cyber_network", Examples: []string{"Kompatibilitaetspruefung vor Update-Installation ausfuehren", "Automatische Plausibilitaetspruefung der Update-Datei", "Pruefprotokoll fuer jedes eingespieltes Update erstellen"}},
{ID: "M086", ReductionType: "protection", SubType: "cybersecurity", Name: "Update-Rollback", Description: "Ein Mechanismus ermoeglicht das automatische Zuruecksetzen auf die vorherige Softwareversion, falls ein Update fehlschlaegt.", HazardCategory: "cyber_network", Examples: []string{"Dual-Boot-System fuer Safety-SPS bereitstellen", "Automatischen Rollback bei gescheitertem Update ausfuehren", "Backup der alten Firmware vor jedem Update erstellen"}},
{ID: "M087", ReductionType: "protection", SubType: "cybersecurity", Name: "Integritaetspruefung", Description: "Die Integritaet der Steuerungssoftware und Konfiguration wird regelmaessig automatisch ueberprueft.", HazardCategory: "cyber_network", Examples: []string{"CRC-Pruefung des Sicherheitsprogramms bei jedem Start", "Laufende Hash-Verifizierung der Firmware im Betrieb", "Zyklische Integritaetspruefung der Parameterdaten"}},
{ID: "M088", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Bootkette", Description: "Der Startvorgang der Steuerung wird durch eine sichere Bootkette geschuetzt, die nur vertrauenswuerdige Software laed.", HazardCategory: "cyber_network", Examples: []string{"Secure Boot im BIOS der Steuerung aktivieren", "Chain-of-Trust vom Bootloader bis zur Applikation aufbauen", "Hardware-Sicherheitsmodul fuer Boot-Verifizierung einsetzen"}},
{ID: "M089", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Firmware", Description: "Die Firmware der Steuerungskomponenten ist gegen unbefugte Aenderung geschuetzt und wird regelmaessig aktualisiert.", HazardCategory: "cyber_network", Examples: []string{"Schreibschutz fuer Firmware aktivieren", "Firmware-Versionskontrolle implementieren", "Nur vom Hersteller freigegebene Firmware einsetzen"}},
{ID: "M090", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Parameteraenderung", Description: "Aenderungen an sicherheitsrelevanten Maschinenparametern erfordern eine Authentifizierung und werden protokolliert.", HazardCategory: "cyber_network", Examples: []string{"Parameterschutz ueber Zugangsstufen realisieren", "Aenderungsprotokoll fuer sicherheitsrelevante Parameter fuehren", "Vier-Augen-Prinzip bei Safety-Parameteraenderungen umsetzen"}},
{ID: "M091", ReductionType: "protection", SubType: "monitoring", Name: "Audit-Trail", Description: "Alle sicherheitsrelevanten Aktionen und Ereignisse werden mit Zeitstempel und Benutzerkennung unveraenderbar protokolliert.", HazardCategory: "cyber_network", Examples: []string{"Sicherheitsereignisse in geschuetztem Logfile speichern", "Benutzerzugriffe auf Safety-Parameter aufzeichnen", "Aenderungshistorie fuer Sicherheitskonfiguration fuehren"}},
{ID: "M092", ReductionType: "protection", SubType: "monitoring", Name: "Alarmierung", Description: "Bei sicherheitsrelevanten Zustandsaenderungen werden optische und akustische Alarme ausgeloest.", HazardCategory: "general", Examples: []string{"Signalleuchte bei Warnung gelb, bei Gefahr rot schalten", "Akustischen Alarm bei Schutztuerverletzung ausloesen", "Blinkende Warnleuchte vor Maschinenstart aktivieren"}},
{ID: "M093", ReductionType: "protection", SubType: "monitoring", Name: "Zustandsueberwachung", Description: "Der Maschinenzustand wird kontinuierlich ueberwacht und Abweichungen vom Normalzustand werden fruehzeitig erkannt.", HazardCategory: "general", Examples: []string{"Condition-Monitoring-System fuer Lager installieren", "Trendanalyse fuer Motorstroeme durchfuehren", "Zustandsbasierte Wartungsplanung implementieren"}},
{ID: "M094", ReductionType: "protection", SubType: "monitoring", Name: "Temperaturueberwachung", Description: "Temperatursensoren ueberwachen sicherheitskritische Stellen und loesen bei Grenzwertueberschreitung eine Schutzreaktion aus.", HazardCategory: "thermal", Examples: []string{"Temperaturfuehler an Motorwicklungen installieren", "Thermoelement an Hydraulikoeltank montieren", "Infrarot-Temperatursensor an Lagergehaeuse anbringen"}},
{ID: "M095", ReductionType: "protection", SubType: "monitoring", Name: "Vibrationsueberwachung", Description: "Schwingungssensoren erkennen erhoehte Vibrationen an rotierenden Teilen und warnen vor drohendem Komponentenversagen.", HazardCategory: "noise_vibration", Examples: []string{"Beschleunigungssensoren an Hauptlagern anbringen", "Schwingungsanalyse-System fuer Spindeln einrichten", "Grenzwertbasierte Vibrationswarnung konfigurieren"}},
{ID: "M096", ReductionType: "protection", SubType: "fluid_protection", Name: "Druckueberwachung", Description: "Der Druck in hydraulischen und pneumatischen Systemen wird kontinuierlich ueberwacht und bei Grenzwertueberschreitung wird eine Schutzreaktion ausgeloest.", HazardCategory: "pneumatic_hydraulic", Examples: []string{"Druckschalter in Hydraulik-Hauptleitung einbauen", "Pneumatik-Druckueberwachung mit Abschaltung konfigurieren", "Differenzdruck-Ueberwachung an Filtern installieren"}},
{ID: "M097", ReductionType: "protection", SubType: "monitoring", Name: "Stromueberwachung", Description: "Die Stromaufnahme sicherheitskritischer Antriebe wird ueberwacht und bei Ueberlast oder Kurzschluss wird abgeschaltet.", HazardCategory: "electrical", Examples: []string{"Motorschutzschalter an jedem Antrieb vorsehen", "Strommessung an Servoachsen fuer Kollisionserkennung nutzen", "Fehlerstrom-Schutzeinrichtung installieren"}},
{ID: "M098", ReductionType: "protection", SubType: "emergency_stop", Name: "Notabschaltung", Description: "Eine Notabschaltung trennt die Maschine sofort von der Energieversorgung, wenn eine unmittelbare Gefahr fuer Leib und Leben besteht.", HazardCategory: "general", Examples: []string{"Notabschaltung der Stromversorgung am Hauptschalter", "Schnellablass fuer Hydraulikdruck bei Notabschaltung", "Automatische Entlueftung der Pneumatik bei Notstopp"}},
{ID: "M099", ReductionType: "protection", SubType: "monitoring", Name: "Sicherheitsueberwachung", Description: "Alle sicherheitsrelevanten Funktionen werden zyklisch auf korrekte Funktion geprueft und Fehler werden erkannt.", HazardCategory: "general", Examples: []string{"Zyklischen Funktionstest der Sicherheitskette durchfuehren", "Online-Diagnose fuer Sicherheitsrelais aktivieren", "Periodische Pruefung der Not-Halt-Funktion"}},
{ID: "M100", ReductionType: "protection", SubType: "electrical_protection", Name: "Sichere Energieentladung", Description: "Nach dem Abschalten entladen sich alle gespeicherten Energien kontrolliert, bevor der Zugang zum Gefahrbereich freigegeben wird.", HazardCategory: "electrical", Examples: []string{"Entladewiderstaende fuer Zwischenkreiskondensatoren vorsehen", "Entlueftungsventil fuer Druckspeicher automatisch betaetigen", "Federspeicherbremse nach Energieabschaltung kontrolliert loesen"}},
{ID: "M101", ReductionType: "protection", SubType: "monitoring", Name: "Automatische Diagnose", Description: "Integrierte Diagnosefunktionen erkennen Fehler in sicherheitsrelevanten Komponenten und melden diese dem Bediener.", HazardCategory: "software_control", Examples: []string{"Automatische Sensordiagnose bei Maschinenstart", "Fehlerspeicher mit Diagnose-Codes am HMI anzeigen", "Remote-Diagnose fuer Sicherheitssteuerung einrichten"}},
{ID: "M102", ReductionType: "protection", SubType: "monitoring", Name: "Selbsttest", Description: "Sicherheitsrelevante Baugruppen fuehren bei jedem Start oder zyklisch automatische Selbsttests durch und melden erkannte Fehler.", HazardCategory: "software_control", Examples: []string{"Anlauftestung des Lichtgitters bei jedem Maschinenstart", "ROM-CRC-Pruefung bei Steuerungsstart durchfuehren", "Zyklischer Relaistest mit Rueckmeldesignal"}},
{ID: "M103", ReductionType: "protection", SubType: "safety_control", Name: "Watchdog", Description: "Ein Watchdog-Timer ueberwacht die Steuerungssoftware und loest bei Ausbleiben des Ruecksetzsignals einen sicheren Zustand aus.", HazardCategory: "software_control", Examples: []string{"Hardware-Watchdog auf Safety-SPS aktivieren", "Fenster-Watchdog mit engem Zeitfenster konfigurieren", "Externen Watchdog fuer diversitaere Ueberwachung einsetzen"}},
{ID: "M104", ReductionType: "protection", SubType: "monitoring", Name: "Redundante Sensorik", Description: "Sicherheitskritische Messstellen werden mit mindestens zwei unabhaengigen Sensoren ueberwacht und die Signale auf Plausibilitaet verglichen.", HazardCategory: "software_control", Examples: []string{"Zweikanalige Positionserfassung an Sicherheitsachse", "Diversitaere Druckmessung mit unterschiedlichen Messprinzipien", "Redundante Temperatursensoren an kritischen Stellen"}},
{ID: "M105", ReductionType: "protection", SubType: "monitoring", Name: "Redundante Aktorik", Description: "Sicherheitskritische Aktoren sind redundant ausgefuehrt, sodass bei Ausfall eines Aktors die Sicherheitsfunktion erhalten bleibt.", HazardCategory: "software_control", Examples: []string{"Doppelte Abschaltventile in Reihe schalten", "Redundante Bremsen mit diversitaerem Wirkprinzip einsetzen", "Zweikanalige Schuetze fuer Motorabschaltung verwenden"}},
{ID: "M106", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Kommunikationsprotokolle", Description: "Fuer die Kommunikation zwischen Steuerungskomponenten werden sichere und authentifizierte Industrieprotokolle eingesetzt.", HazardCategory: "cyber_network", Examples: []string{"PROFIsafe fuer sichere SPS-Kommunikation einsetzen", "CIP Safety fuer EtherNet/IP-Netzwerke konfigurieren", "FSoE fuer EtherCAT-Safety-Kommunikation verwenden"}},
{ID: "M107", ReductionType: "protection", SubType: "cybersecurity", Name: "Zugriffskontrollsystem", Description: "Ein umfassendes Zugriffskontrollsystem regelt und dokumentiert physische und logische Zugriffe auf alle Maschinenkomponenten.", HazardCategory: "cyber_network", Examples: []string{"Zentrale Benutzerverwaltung fuer alle Steuerungssysteme", "Physische Schluesselsysteme fuer Schaltschraenke einsetzen", "Zugriffsprotokolle fuer alle Steuerungszugriffe fuehren"}},
{ID: "M108", ReductionType: "protection", SubType: "monitoring", Name: "Anomalieerkennung", Description: "Ein System zur Erkennung ungewoehnlicher Verhaltensmuster im Maschinenbetrieb warnt fruehzeitig vor potenziellen Sicherheitsproblemen.", HazardCategory: "ai_specific", Examples: []string{"Maschinelles Lernen fuer Normalbetriebsprofil einsetzen", "Statistische Prozesskontrolle fuer Sicherheitsparameter", "Netzwerk-Anomalieerkennung fuer Industrieprotokolle"}},
{ID: "M109", ReductionType: "protection", SubType: "monitoring", Name: "Sicherheitsmonitor", Description: "Ein unabhaengiger Sicherheitsmonitor ueberwacht die Einhaltung aller Sicherheitsbedingungen parallel zur Standardsteuerung.", HazardCategory: "software_control", Examples: []string{"Unabhaengigen Safety-Monitor fuer Roboterbewegung einsetzen", "Externen Sicherheitsmonitor fuer Drehzahlueberwachung nutzen", "Separaten Sicherheitsrechner fuer Plausibilitaetspruefung"}},
{ID: "M110", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Konfigurationsverwaltung", Description: "Alle Konfigurationsaenderungen an sicherheitsrelevanten Systemen werden versioniert, dokumentiert und auf Konsistenz geprueft.", HazardCategory: "cyber_network", Examples: []string{"Versionsverwaltung fuer Safety-SPS-Programme einrichten", "Konfigurationsaenderungen nur ueber freigegebenen Prozess", "Automatische Konfigurationssicherung bei jeder Aenderung"}},
{ID: "M111", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere API", Description: "Programmierschnittstellen zur Maschinensteuerung sind gegen unautorisierte Nutzung und fehlerhafte Eingaben geschuetzt.", HazardCategory: "cyber_network", Examples: []string{"API-Zugriff nur mit gueltigem Token ermoeglichen", "Eingabevalidierung fuer alle API-Parameter durchfuehren", "Rate-Limiting fuer Steuerungs-API konfigurieren"}},
{ID: "M112", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Datenvalidierung", Description: "Alle eingehenden Daten und Befehle werden auf Gueltigkeit, Plausibilitaet und zulaessigen Wertebereich geprueft.", HazardCategory: "cyber_network", Examples: []string{"Wertebereichspruefung fuer Sollwert-Vorgaben implementieren", "Plausibilitaetspruefung fuer Sensordaten durchfuehren", "Typenpruefung fuer Kommunikationspakete aktivieren"}},
{ID: "M113", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Protokollierung", Description: "Alle sicherheitsrelevanten Vorgaenge werden manipulationssicher protokolliert und fuer Audits aufbewahrt.", HazardCategory: "cyber_network", Examples: []string{"Append-Only-Log fuer Sicherheitsereignisse einrichten", "Logdaten auf separatem geschuetztem Speicher ablegen", "Regelnmaessigen Log-Export fuer Archivierung durchfuehren"}},
{ID: "M114", ReductionType: "protection", SubType: "cybersecurity", Name: "Sichere Zeitstempel", Description: "Alle protokollierten Ereignisse erhalten zuverlaessige Zeitstempel aus einer synchronisierten und gesicherten Zeitquelle.", HazardCategory: "cyber_network", Examples: []string{"NTP-Synchronisation fuer alle Steuerungskomponenten aktivieren", "Hardwareuhr mit Batteriesicherung verwenden", "Zeitsynchronisation der Safety-SPS ueberwachen"}},
{ID: "M115", ReductionType: "protection", SubType: "safety_control", Name: "Sichere Speicherverwaltung", Description: "Die Steuerungssoftware verwendet sichere Speicherverwaltung, um Datenverlust und speicherbasierte Angriffe zu verhindern.", HazardCategory: "software_control", Examples: []string{"Speicherschutz fuer Safety-Programmbereiche aktivieren", "Stack-Overflow-Schutz implementieren", "Dynamische Speicherallokation in Safety-Software vermeiden"}},
{ID: "M116", ReductionType: "protection", SubType: "safety_control", Name: "Sichere Ressourcenverwaltung", Description: "Steuerungsressourcen werden so verwaltet, dass Engpaesse bei CPU, Speicher oder Kommunikation keine Sicherheitsfunktion beeintraechtigen.", HazardCategory: "software_control", Examples: []string{"CPU-Auslastung der Safety-SPS ueberwachen", "Priorisierung der sicherheitsrelevanten Tasks sicherstellen", "Kommunikationsbandbreite fuer Safety-Protokolle reservieren"}},
{ID: "M117", ReductionType: "protection", SubType: "safety_control", Name: "Sichere Fehlerbehandlung", Description: "Jeder erkannte Fehler wird systematisch behandelt und in einen definierten sicheren Zustand ueberfuehrt.", HazardCategory: "software_control", Examples: []string{"Exception-Handler fuer alle kritischen Codebereiche implementieren", "Fehlerkategorien mit zugeordneten Reaktionen definieren", "Unbehandelte Fehler loesen sicheren Stopp aus"}},
{ID: "M118", ReductionType: "protection", SubType: "safety_control", Name: "Sichere Recovery", Description: "Nach einem Fehler oder Ausfall wird die Maschine in einen definierten Ausgangszustand zurueckgesetzt, bevor der Betrieb fortgesetzt werden kann.", HazardCategory: "software_control", Examples: []string{"Referenzfahrt nach Steuerungswiederanlauf erzwingen", "Konfigurationscheck nach Recovery durchfuehren", "Schrittweisen Wiederanlauf mit Bedienerquittierung"}},
{ID: "M119", ReductionType: "protection", SubType: "safety_control", Name: "Sichere Degradationsstrategie", Description: "Bei Teilausfaellen wird die Maschine in einen Modus mit reduzierter Leistung aber erhaltener Sicherheit uebergefuehrt.", HazardCategory: "software_control", Examples: []string{"Reduzierte Geschwindigkeit bei Sensorausfall aktivieren", "Einschraenkung auf Grundfunktionen bei Teilausfall", "Automatischer Wechsel von Automatik auf Handbetrieb"}},
{ID: "M120", ReductionType: "protection", SubType: "safety_control", Name: "Sichere Abschaltung bei Fehler", Description: "Bei schwerwiegenden Fehlern wird die Maschine automatisch und sicher abgeschaltet, um Personen- und Sachschaeden zu vermeiden.", HazardCategory: "software_control", Examples: []string{"Stopp-Kategorie 0 bei kritischem Sicherheitsfehler ausfuehren", "Kontrolliertes Herunterfahren bei erkanntem Komponentenausfall", "Energietrennung bei nicht behebbarem Fehler einleiten"}},
// ====================================================================
// Type 3: Information (ReductionType: "information") — Benutzerinformation
// 40 entries: M121-M160
// ====================================================================
{ID: "M121", ReductionType: "information", SubType: "signage", Name: "Warnhinweis", Description: "Gut sichtbare Warnhinweise weisen den Bediener auf bestehende Restrisiken und erforderliche Vorsichtsmassnahmen hin.", HazardCategory: "general", Examples: []string{"Warnschild fuer Quetschgefahr an Schutztuer anbringen", "Hinweis auf automatischen Anlauf an der Maschine", "Warnaufkleber fuer heisse Oberflaeche am Gehaeuse"}},
{ID: "M122", ReductionType: "information", SubType: "signage", Name: "Gefahrenkennzeichnung", Description: "Gefahrbereiche und -stellen werden durch normgerechte Kennzeichnung dauerhaft markiert.", HazardCategory: "general", Examples: []string{"Bodenmarkierung um Gefahrbereich anbringen", "Warnmarkierung an rotierenden Teilen aufkleben", "Gefahrenzone mit gelb-schwarzer Schraffur kennzeichnen"}},
{ID: "M123", ReductionType: "information", SubType: "manual", Name: "Betriebsanweisung", Description: "Eine verstaendliche Betriebsanweisung beschreibt den sicheren Betrieb der Maschine in allen vorgesehenen Betriebsarten.", HazardCategory: "general", Examples: []string{"Betriebsanweisung am Bedienplatz aushangen", "Taeglich zu beachtende Sicherheitshinweise dokumentieren", "Betriebsarten und zugehoerige Schutzfunktionen beschreiben"}},
{ID: "M124", ReductionType: "information", SubType: "manual", Name: "Wartungsanweisung", Description: "Detaillierte Wartungsanweisungen beschreiben alle planmaessigen Wartungsarbeiten mit den erforderlichen Sicherheitsmassnahmen.", HazardCategory: "general", Examples: []string{"Schritt-fuer-Schritt-Wartungsanleitung erstellen", "Erforderliche Sicherheitsmassnahmen vor jeder Wartungstaetikeit", "Wartungsintervalle und Pruefpunkte auflisten"}},
{ID: "M125", ReductionType: "information", SubType: "manual", Name: "Reinigungsanweisung", Description: "Reinigungsanweisungen geben die sichere Vorgehensweise bei der Reinigung der Maschine und ihrer Komponenten vor.", HazardCategory: "general", Examples: []string{"Zulaessige Reinigungsmittel auflisten", "Reinigungsprozedur bei abgeschalteter Maschine beschreiben", "Bereiche mit besonderen Reinigungsanforderungen kennzeichnen"}},
{ID: "M126", ReductionType: "information", SubType: "training", Name: "Schulungsprogramm", Description: "Ein strukturiertes Schulungsprogramm vermittelt allen Bedienern die sicherheitsrelevanten Kenntnisse und Fertigkeiten.", HazardCategory: "general", Examples: []string{"Einweisungsprogramm fuer neue Maschinenbediener erstellen", "Jaehrliche Auffrischungsschulung durchfuehren", "Schulungsnachweise dokumentieren und archivieren"}},
{ID: "M127", ReductionType: "information", SubType: "training", Name: "Sicherheitsunterweisung", Description: "Regelmaessige Sicherheitsunterweisungen informieren die Beschaeftigten ueber Gefaehrdungen und die korrekte Nutzung von Schutzeinrichtungen.", HazardCategory: "general", Examples: []string{"Arbeitsplatzspezifische Sicherheitsunterweisung durchfuehren", "Not-Halt-Uebung mit allen Bedienern regelmaessig durchfuehren", "Unterweisung zum sicheren Umgang mit Gefahrstoffen"}},
{ID: "M128", ReductionType: "information", SubType: "manual", Name: "Bedienungsanleitung", Description: "Die Bedienungsanleitung beschreibt umfassend die sichere Bedienung, Installation, Inbetriebnahme und Ausserbetriebnahme der Maschine.", HazardCategory: "general", Examples: []string{"Vollstaendige Bedienungsanleitung in Landessprache bereitstellen", "Bebilderte Schritt-fuer-Schritt-Anleitungen erstellen", "Kapitel zu bestimmungsgemaesser Verwendung aufnehmen"}},
{ID: "M129", ReductionType: "information", SubType: "manual", Name: "Servicehandbuch", Description: "Das Servicehandbuch stellt Servicetechnikern alle Informationen fuer sichere Diagnose, Reparatur und Instandsetzung bereit.", HazardCategory: "general", Examples: []string{"Schaltplaene und Hydraulikplaene beifuegen", "Diagnoseprozeduren fuer alle Fehlercodes beschreiben", "Ersatzteillisten mit sicherheitsrelevanten Komponenten kennzeichnen"}},
{ID: "M130", ReductionType: "information", SubType: "manual", Name: "Notfallanweisung", Description: "Die Notfallanweisung beschreibt die Sofortmassnahmen bei Unfaellen und Stoerungen an der Maschine.", HazardCategory: "general", Examples: []string{"Notfallplan an der Maschine aushangen", "Erste-Hilfe-Massnahmen bei maschinenspezifischen Verletzungen", "Verhalten bei Medienaustritt beschreiben"}},
{ID: "M131", ReductionType: "information", SubType: "ppe", Name: "PSA-Vorgaben", Description: "Vorgeschriebene Persoenliche Schutzausruestung wird fuer jeden Arbeitsbereich und jede Taetikeit festgelegt.", HazardCategory: "general", Examples: []string{"Gehoerschutz ab 85 dB(A) vorschreiben", "Schutzbrille bei Spanabnahme fordern", "Sicherheitsschuhe im gesamten Produktionsbereich verlangen"}},
{ID: "M132", ReductionType: "information", SubType: "signage", Name: "Sicherheitskennzeichnung", Description: "Normgerechte Sicherheitskennzeichnung informiert ueber Gebote, Verbote, Warnungen und Rettungswege.", HazardCategory: "general", Examples: []string{"Gebotszeichen fuer Gehoerschutz anbringen", "Verbotszeichen an gesperrten Zugaengen befestigen", "Rettungszeichen fuer Notausgaenge und Erste-Hilfe-Stellen"}},
{ID: "M133", ReductionType: "information", SubType: "organizational", Name: "Zugangsbeschraenkung", Description: "Organisatorische Regelungen legen fest, wer Zugang zum Gefahrbereich erhalten darf und unter welchen Bedingungen.", HazardCategory: "general", Examples: []string{"Zugangsberechtigungsliste fuer Gefahrbereiche fuehren", "Begleitpflicht fuer Besucher im Produktionsbereich anordnen", "Zugangsverbot fuer nicht unterwiesene Personen kennzeichnen"}},
{ID: "M134", ReductionType: "information", SubType: "training", Name: "Benutzerrollenbeschreibung", Description: "Fuer jede Benutzerrolle sind die Aufgaben, Verantwortlichkeiten und erforderlichen Qualifikationen dokumentiert.", HazardCategory: "general", Examples: []string{"Rollenbeschreibung fuer Maschinenbediener erstellen", "Qualifikationsanforderungen fuer Instandhalter definieren", "Verantwortlichkeiten des Schichtfuehrers dokumentieren"}},
{ID: "M135", ReductionType: "information", SubType: "organizational", Name: "Wartungsplan", Description: "Ein detaillierter Wartungsplan legt die Intervalle und den Umfang aller planmaessigen Wartungstaetigkeiten fest.", HazardCategory: "general", Examples: []string{"Taeglich zu pruefende Sicherheitseinrichtungen auflisten", "Woechentlichen Schmierplan erstellen", "Jaehrliche Hauptinspektion planen und dokumentieren"}},
{ID: "M136", ReductionType: "information", SubType: "organizational", Name: "Inspektionsplan", Description: "Der Inspektionsplan definiert Art und Haeufigkeit der Inspektionen sicherheitsrelevanter Maschinenkomponenten.", HazardCategory: "general", Examples: []string{"Tagesinspektion fuer Schutzeinrichtungen festlegen", "Quartalinspektion fuer Hydraulikleitungen einplanen", "Jaehrliche Sicherheitstechnische Pruefung terminieren"}},
{ID: "M137", ReductionType: "information", SubType: "organizational", Name: "Pruefplan", Description: "Der Pruefplan legt fest, welche Pruefungen an sicherheitsrelevanten Bauteilen in welchen Intervallen durchzufuehren sind.", HazardCategory: "general", Examples: []string{"Wiederkehrende Pruefung von Druckbehaeltern planen", "Pruefung der elektrischen Sicherheit nach DGUV V3 terminieren", "Belastungstest fuer Hebezeuge jaehrlich durchfuehren"}},
{ID: "M138", ReductionType: "information", SubType: "organizational", Name: "Softwareupdateanleitung", Description: "Die Anleitung beschreibt das sichere Vorgehen beim Einspielen von Software- und Firmware-Updates auf der Maschinensteuerung.", HazardCategory: "software_control", Examples: []string{"Updateprozedur mit Sicherheitshinweisen dokumentieren", "Backup-Erstellung vor jedem Update vorschreiben", "Funktionspruefung nach Update beschreiben"}},
{ID: "M139", ReductionType: "information", SubType: "organizational", Name: "Cyber-Security-Hinweise", Description: "Hinweise zur IT-Sicherheit informieren den Betreiber ueber Massnahmen zum Schutz der Maschinensteuerung vor Cyberangriffen.", HazardCategory: "cyber_network", Examples: []string{"Passwortrichtlinien fuer Steuerungssysteme kommunizieren", "Hinweise zur Netzwerksicherheit bereitstellen", "Regelmaessige Aktualisierung der Sicherheitssoftware empfehlen"}},
{ID: "M140", ReductionType: "information", SubType: "organizational", Name: "Passwortpolicy", Description: "Eine Passwortrichtlinie definiert Mindestanforderungen an Passwoerter fuer den Zugriff auf Steuerungssysteme.", HazardCategory: "cyber_network", Examples: []string{"Mindestlaenge und Komplexitaetsanforderungen festlegen", "Regelmaessigen Passwortwechsel vorschreiben", "Standardpasswoerter bei Inbetriebnahme aendern lassen"}},
{ID: "M141", ReductionType: "information", SubType: "organizational", Name: "Backup-Anweisung", Description: "Die Backup-Anweisung regelt die regelmaessige Sicherung von Steuerungsprogrammen und Konfigurationsdaten.", HazardCategory: "software_control", Examples: []string{"Woechentliches Backup der SPS-Programme vorschreiben", "Sicherung der Parameterdaten nach jeder Aenderung", "Backup-Medien an sicherem Ort aufbewahren"}},
{ID: "M142", ReductionType: "information", SubType: "organizational", Name: "Incident-Reporting", Description: "Ein Verfahren zur Meldung und Dokumentation von Sicherheitsvorfaellen stellt sicher, dass alle Vorfaelle erfasst und ausgewertet werden.", HazardCategory: "general", Examples: []string{"Meldeformular fuer Sicherheitsvorfaelle bereitstellen", "Meldekette fuer schwere Vorfaelle definieren", "Vorfallanalyse und Massnahmenverfolgung dokumentieren"}},
{ID: "M143", ReductionType: "information", SubType: "organizational", Name: "Stoerungsanweisung", Description: "Die Stoerungsanweisung beschreibt das sichere Vorgehen bei typischen Maschinenstoerungen und deren Behebung.", HazardCategory: "general", Examples: []string{"Haeufige Stoerungsbilder mit Abhilfemassnahmen auflisten", "Sicherheitshinweise vor jeder Stoerungsbeseitigung angeben", "Eskalationsprozess bei nicht behebbaren Stoerungen"}},
{ID: "M144", ReductionType: "information", SubType: "organizational", Name: "Reset-Anweisung", Description: "Die Reset-Anweisung beschreibt die sichere Vorgehensweise zum Quittieren von Fehlern und Wiederanlauf der Maschine.", HazardCategory: "software_control", Examples: []string{"Reset-Prozedur nach Not-Halt dokumentieren", "Voraussetzungen fuer sicheren Wiederanlauf beschreiben", "Pruefschritte vor Produktionsfreigabe nach Reset"}},
{ID: "M145", ReductionType: "information", SubType: "organizational", Name: "Konfigurationsrichtlinie", Description: "Die Konfigurationsrichtlinie legt fest, wie sicherheitsrelevante Parameter dokumentiert, geaendert und freigegeben werden.", HazardCategory: "software_control", Examples: []string{"Parameterliste mit zulaessigen Wertebereichen erstellen", "Aenderungsantragsformular fuer Safety-Parameter bereitstellen", "Freigabeprozess fuer Konfigurationsaenderungen dokumentieren"}},
{ID: "M146", ReductionType: "information", SubType: "organizational", Name: "Update-Freigabeprozess", Description: "Ein definierter Freigabeprozess stellt sicher, dass Software-Updates vor dem Einspielen auf Sicherheit geprueft und freigegeben werden.", HazardCategory: "software_control", Examples: []string{"Testprozedur fuer Updates auf Testmaschine beschreiben", "Freigabeformular mit Unterschrift des Sicherheitsbeauftragten", "Dokumentation der Testerbgebnisse vor Produktivstart"}},
{ID: "M147", ReductionType: "information", SubType: "organizational", Name: "Aenderungsmanagement", Description: "Ein strukturiertes Aenderungsmanagement stellt sicher, dass alle technischen Aenderungen auf ihre Sicherheitswirkung geprueft werden.", HazardCategory: "general", Examples: []string{"Aenderungsantrag mit Sicherheitsbewertung einreichen", "Risikobeurteilung bei jeder technischen Aenderung aktualisieren", "Aenderungshistorie lueckenlos fuehren"}},
{ID: "M148", ReductionType: "information", SubType: "organizational", Name: "Sicherheitsprotokoll", Description: "Ein Sicherheitsprotokoll dokumentiert alle durchgefuehrten Sicherheitspruefungen und deren Ergebnisse.", HazardCategory: "general", Examples: []string{"Pruefprotokoll fuer wiederkehrende Sicherheitspruefungen", "Abnahmeprotokoll nach Umbaumassnahmen", "Funktionspruefungsprotokoll fuer Schutzeinrichtungen"}},
{ID: "M149", ReductionType: "information", SubType: "organizational", Name: "Auditverfahren", Description: "Ein Auditverfahren regelt die regelmaessige Ueberpruefung der Wirksamkeit aller Sicherheitsmassnahmen.", HazardCategory: "general", Examples: []string{"Internes Sicherheitsaudit jaehrlich durchfuehren", "Auditcheckliste fuer Maschinensicherheit erstellen", "Massnahmen aus Auditfeststellungen nachverfolgen"}},
{ID: "M150", ReductionType: "information", SubType: "manual", Name: "Betreiberhandbuch", Description: "Das Betreiberhandbuch fasst alle organisatorischen Pflichten und Verantwortlichkeiten des Maschinenbetreibers zusammen.", HazardCategory: "general", Examples: []string{"Betreiberpflichten aus Maschinenrichtlinie zusammenfassen", "Pruef- und Wartungspflichten dokumentieren", "Verantwortlichkeiten fuer Sicherheitsbeauftragte festlegen"}},
{ID: "M151", ReductionType: "information", SubType: "signage", Name: "Gefahrenpiktogramme", Description: "Normgerechte Piktogramme warnen sprachunabhaengig vor spezifischen Gefaehrdungen an der Maschine.", HazardCategory: "general", Examples: []string{"Piktogramm fuer Handverletzungsgefahr anbringen", "Elektrogefahr-Symbol am Schaltschrank befestigen", "Laserwarnsymbol an Laserbearbeitungsanlage"}},
{ID: "M152", ReductionType: "information", SubType: "marking", Name: "Sicherheitsdiagramme", Description: "Sicherheitsdiagramme visualisieren Sicherheitskreise, Schutzeinrichtungen und deren Zusammenwirken an der Maschine.", HazardCategory: "general", Examples: []string{"Schaltschema des Sicherheitskreises im Schaltschrank aushangen", "Pneumatikschaltplan mit Sicherheitsventilen bereitstellen", "Blockschaltbild der Sicherheitssteuerung dokumentieren"}},
{ID: "M153", ReductionType: "information", SubType: "organizational", Name: "Checklisten", Description: "Standardisierte Checklisten unterstuetzen die systematische Durchfuehrung sicherheitsrelevanter Taetigkeiten.", HazardCategory: "general", Examples: []string{"Taeglich abzuarbeitende Sicherheits-Checkliste erstellen", "Checkliste fuer Schichtwechsel bereitstellen", "Checkliste fuer Wiederanlauf nach Stillstand"}},
{ID: "M154", ReductionType: "information", SubType: "organizational", Name: "Wartungscheckliste", Description: "Eine Wartungscheckliste stellt sicher, dass alle Wartungspunkte systematisch abgearbeitet und dokumentiert werden.", HazardCategory: "general", Examples: []string{"Checkliste fuer woechentliche Wartung erstellen", "Pruefpunkte fuer Oelstand und Filterzustand auflisten", "Wartungsergebnis mit Datum und Unterschrift dokumentieren"}},
{ID: "M155", ReductionType: "information", SubType: "organizational", Name: "Inspektionscheckliste", Description: "Die Inspektionscheckliste leitet die systematische Sichtpruefung aller sicherheitsrelevanten Maschinenkomponenten.", HazardCategory: "general", Examples: []string{"Sichtpruefung der Schutzeinrichtungen auf Vollstaendigkeit", "Funktionspruefung der Not-Halt-Einrichtungen", "Kontrolle der Sicherheitskennzeichnung auf Lesbarkeit"}},
{ID: "M156", ReductionType: "information", SubType: "organizational", Name: "Inbetriebnahmecheckliste", Description: "Die Inbetriebnahmecheckliste stellt sicher, dass vor dem ersten Betrieb alle Sicherheitsvoraussetzungen erfuellt sind.", HazardCategory: "general", Examples: []string{"Schutzeinrichtungen auf korrekte Montage pruefen", "Sicherheitsfunktionen einzeln testen und dokumentieren", "Erdung und Potenzialausgleich messen"}},
{ID: "M157", ReductionType: "information", SubType: "organizational", Name: "Stilllegungscheckliste", Description: "Die Stilllegungscheckliste regelt die sichere Ausserbetriebnahme und Entsorgung der Maschine.", HazardCategory: "general", Examples: []string{"Energiequellen sicher trennen und sichern", "Betriebsstoffe umweltgerecht entsorgen", "Sicherheitsrelevante Komponenten deaktivieren und kennzeichnen"}},
{ID: "M158", ReductionType: "information", SubType: "organizational", Name: "Entsorgungsanleitung", Description: "Die Entsorgungsanleitung beschreibt die fachgerechte und sichere Entsorgung der Maschine und ihrer Betriebsstoffe.", HazardCategory: "material_environmental", Examples: []string{"Gefahrstoffe identifizieren und Entsorgungsweg festlegen", "Recyclingfaehige Materialien kennzeichnen", "Entsorgungsnachweis fuer Betriebsfluide verlangen"}},
{ID: "M159", ReductionType: "information", SubType: "signage", Name: "Sicherheitsplakat", Description: "Ein gut sichtbares Sicherheitsplakat fasst die wichtigsten Sicherheitsregeln fuer den Arbeitsbereich zusammen.", HazardCategory: "general", Examples: []string{"Sicherheitsplakat am Maschinenzugang aushangen", "Wichtigste Verhaltensregeln im Notfall darstellen", "Piktogramme fuer vorgeschriebene PSA abbilden"}},
{ID: "M160", ReductionType: "information", SubType: "organizational", Name: "Notfallkontaktliste", Description: "Eine aktuelle Notfallkontaktliste stellt sicher, dass im Notfall alle relevanten Ansprechpartner schnell erreichbar sind.", HazardCategory: "general", Examples: []string{"Notfallnummern am Bedienplatz aushangen", "Kontaktdaten von Sicherheitsbeauftragten und Ersthelfern", "Herstellerhotline fuer technische Notfaelle bereithalten"}},
}
}

View File

@@ -71,11 +71,13 @@ func clampFloat(v, lo, hi float64) float64 {
// CalculateInherentRisk computes the inherent risk score.
//
// Formula:
// - avoidance == 0: S × E × P (backward-compatible, no avoidance factor)
// - avoidance > 0: S × E × P × (A / 3.0) (3 = neutral, no influence)
// Dual-mode formula for backward compatibility:
// - avoidance == 0: Legacy S × E × P (no avoidance factor)
// - avoidance >= 1: ISO 12100 mode S × F × P × A (direct multiplication)
//
// In ISO mode, the factors represent:
// - S: Severity (1-5), F: Frequency/Exposure (1-5), P: Probability (1-5), A: Avoidance (1-5)
//
// Avoidance scale: 1=leicht vermeidbar, 3=neutral, 5=nicht vermeidbar.
// Each factor is expected in the range 1-5 and will be clamped if out of range.
func (e *RiskEngine) CalculateInherentRisk(severity, exposure, probability, avoidance int) float64 {
s := clamp(severity, 1, 5)
@@ -85,8 +87,9 @@ func (e *RiskEngine) CalculateInherentRisk(severity, exposure, probability, avoi
if avoidance <= 0 {
return base
}
// ISO 12100 mode: direct S × F × P × A multiplication (no /3.0 normalization)
a := clamp(avoidance, 1, 5)
return base * (float64(a) / 3.0)
return base * float64(a)
}
// CalculateControlEffectiveness computes the control effectiveness score.
@@ -143,6 +146,68 @@ func (e *RiskEngine) DetermineRiskLevel(residualRisk float64) RiskLevel {
}
}
// DetermineRiskLevelISO classifies the inherent risk using ISO 12100 thresholds.
//
// Thresholds (for S×F×P×A, max 625):
// - > 300: not_acceptable
// - 151-300: very_high
// - 61-150: high
// - 21-60: medium
// - 1-20: low
func (e *RiskEngine) DetermineRiskLevelISO(risk float64) RiskLevel {
switch {
case risk > 300:
return RiskLevelNotAcceptable
case risk >= 151:
return RiskLevelVeryHigh
case risk >= 61:
return RiskLevelHigh
case risk >= 21:
return RiskLevelMedium
default:
return RiskLevelLow
}
}
// ValidateProtectiveMeasureHierarchy checks if an information-only measure
// (ReductionType "information") is being used as the primary mitigation
// when design or technical measures could be applied.
// Returns a list of warning messages.
func (e *RiskEngine) ValidateProtectiveMeasureHierarchy(reductionType ReductionType, existingMitigations []Mitigation) []string {
var warnings []string
if reductionType != ReductionTypeInformation {
return warnings
}
// Check if there are any design or protective measures already
hasDesign := false
hasProtective := false
for _, m := range existingMitigations {
if m.Status == MitigationStatusRejected {
continue
}
switch m.ReductionType {
case ReductionTypeDesign:
hasDesign = true
case ReductionTypeProtective:
hasProtective = true
}
}
if !hasDesign && !hasProtective {
warnings = append(warnings,
"Hinweismassnahmen (Typ 3) duerfen NICHT als alleinige Primaermassnahme verwendet werden. "+
"Pruefen Sie zuerst, ob konstruktive (Typ 1) oder technische Schutzmassnahmen (Typ 2) moeglich sind.")
} else if !hasDesign {
warnings = append(warnings,
"Es liegen keine konstruktiven Massnahmen (Typ 1) vor. "+
"Pruefen Sie, ob eine inhaerent sichere Konstruktion die Gefaehrdung beseitigen kann.")
}
return warnings
}
// IsAcceptable determines whether the residual risk is acceptable based on
// the ALARP (As Low As Reasonably Practicable) principle and EU AI Act thresholds.
//
@@ -200,7 +265,14 @@ func (e *RiskEngine) ComputeRisk(req RiskComputeInput) (*RiskComputeResult, erro
inherentRisk := e.CalculateInherentRisk(req.Severity, req.Exposure, req.Probability, req.Avoidance)
controlEff := e.CalculateControlEffectiveness(req.ControlMaturity, req.ControlCoverage, req.TestEvidence)
residualRisk := e.CalculateResidualRisk(req.Severity, req.Exposure, req.Probability, controlEff)
riskLevel := e.DetermineRiskLevel(residualRisk)
// ISO 12100 mode uses ISO thresholds for inherent risk classification
var riskLevel RiskLevel
if req.Avoidance >= 1 {
riskLevel = e.DetermineRiskLevelISO(inherentRisk)
} else {
riskLevel = e.DetermineRiskLevel(residualRisk)
}
acceptable, reason := e.IsAcceptable(residualRisk, false, req.HasJustification)
return &RiskComputeResult{

View File

@@ -912,6 +912,242 @@ func TestClamp(t *testing.T) {
}
}
// ============================================================================
// 10. ISO 12100 Mode — S × F × P × A (direct multiplication)
// ============================================================================
func TestCalculateInherentRisk_ISO12100Mode(t *testing.T) {
e := NewRiskEngine()
tests := []struct {
name string
s, f, p, a int
expected float64
}{
// Minimum: 1×1×1×1 = 1
{"min 1×1×1×1", 1, 1, 1, 1, 1},
// Maximum: 5×5×5×5 = 625
{"max 5×5×5×5", 5, 5, 5, 5, 625},
// Typical mid-range: 3×3×3×3 = 81
{"mid 3×3×3×3", 3, 3, 3, 3, 81},
// High severity, low avoidance: 5×3×4×1 = 60
{"high S low A", 5, 3, 4, 1, 60},
// All factors high: 4×4×4×4 = 256
{"high 4×4×4×4", 4, 4, 4, 4, 256},
// Low risk: 2×1×2×1 = 4
{"low risk", 2, 1, 2, 1, 4},
// At not_acceptable boundary: 5×5×3×5 = 375
{"above 300", 5, 5, 3, 5, 375},
// At very_high boundary: 4×3×4×4 = 192
{"very high range", 4, 3, 4, 4, 192},
// At high boundary: 3×3×3×3 = 81
{"high range", 3, 3, 3, 3, 81},
// At medium range: 2×3×3×2 = 36
{"medium range", 2, 3, 3, 2, 36},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := e.CalculateInherentRisk(tt.s, tt.f, tt.p, tt.a)
if !almostEqual(result, tt.expected) {
t.Errorf("CalculateInherentRisk(%d, %d, %d, %d) = %v, want %v",
tt.s, tt.f, tt.p, tt.a, result, tt.expected)
}
})
}
}
func TestDetermineRiskLevelISO(t *testing.T) {
e := NewRiskEngine()
tests := []struct {
name string
risk float64
expected RiskLevel
}{
// not_acceptable: > 300
{"not_acceptable at 301", 301, RiskLevelNotAcceptable},
{"not_acceptable at 625", 625, RiskLevelNotAcceptable},
{"not_acceptable at 400", 400, RiskLevelNotAcceptable},
// very_high: 151-300
{"very_high at 300", 300, RiskLevelVeryHigh},
{"very_high at 151", 151, RiskLevelVeryHigh},
{"very_high at 200", 200, RiskLevelVeryHigh},
// high: 61-150
{"high at 150", 150, RiskLevelHigh},
{"high at 61", 61, RiskLevelHigh},
{"high at 100", 100, RiskLevelHigh},
// medium: 21-60
{"medium at 60", 60, RiskLevelMedium},
{"medium at 21", 21, RiskLevelMedium},
{"medium at 40", 40, RiskLevelMedium},
// low: 1-20
{"low at 20", 20, RiskLevelLow},
{"low at 1", 1, RiskLevelLow},
{"low at 10", 10, RiskLevelLow},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := e.DetermineRiskLevelISO(tt.risk)
if result != tt.expected {
t.Errorf("DetermineRiskLevelISO(%v) = %v, want %v", tt.risk, result, tt.expected)
}
})
}
}
func TestAvoidanceBackwardCompat(t *testing.T) {
e := NewRiskEngine()
// With avoidance=0, formula must remain S×E×P (legacy mode)
tests := []struct {
s, ex, p int
expected float64
}{
{5, 5, 5, 125},
{3, 3, 3, 27},
{1, 1, 1, 1},
{4, 2, 5, 40},
}
for _, tt := range tests {
result := e.CalculateInherentRisk(tt.s, tt.ex, tt.p, 0)
if !almostEqual(result, tt.expected) {
t.Errorf("Legacy mode: CalculateInherentRisk(%d,%d,%d,0) = %v, want %v",
tt.s, tt.ex, tt.p, result, tt.expected)
}
}
}
func TestValidateProtectiveMeasureHierarchy(t *testing.T) {
e := NewRiskEngine()
tests := []struct {
name string
reductionType ReductionType
existing []Mitigation
wantWarnings int
}{
{
name: "design measure — no warning",
reductionType: ReductionTypeDesign,
existing: nil,
wantWarnings: 0,
},
{
name: "information without any — full warning",
reductionType: ReductionTypeInformation,
existing: nil,
wantWarnings: 1,
},
{
name: "information with design — no warning",
reductionType: ReductionTypeInformation,
existing: []Mitigation{
{ReductionType: ReductionTypeDesign, Status: MitigationStatusImplemented},
{ReductionType: ReductionTypeProtective, Status: MitigationStatusPlanned},
},
wantWarnings: 0,
},
{
name: "information with only protective — missing design warning",
reductionType: ReductionTypeInformation,
existing: []Mitigation{
{ReductionType: ReductionTypeProtective, Status: MitigationStatusImplemented},
},
wantWarnings: 1,
},
{
name: "information with rejected measures — full warning",
reductionType: ReductionTypeInformation,
existing: []Mitigation{
{ReductionType: ReductionTypeDesign, Status: MitigationStatusRejected},
{ReductionType: ReductionTypeProtective, Status: MitigationStatusRejected},
},
wantWarnings: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
warnings := e.ValidateProtectiveMeasureHierarchy(tt.reductionType, tt.existing)
if len(warnings) != tt.wantWarnings {
t.Errorf("got %d warnings, want %d: %v", len(warnings), tt.wantWarnings, warnings)
}
})
}
}
func TestComputeRisk_ISOMode(t *testing.T) {
e := NewRiskEngine()
// ISO mode: avoidance >= 1 → uses DetermineRiskLevelISO for inherent risk classification
tests := []struct {
name string
input RiskComputeInput
wantLevel RiskLevel
}{
{
name: "ISO low risk",
input: RiskComputeInput{
Severity: 2, Exposure: 1, Probability: 2, Avoidance: 1,
ControlMaturity: 2, ControlCoverage: 0.5, TestEvidence: 0.5,
},
wantLevel: RiskLevelLow, // 2×1×2×1 = 4 → low
},
{
name: "ISO medium risk",
input: RiskComputeInput{
Severity: 3, Exposure: 2, Probability: 3, Avoidance: 2,
ControlMaturity: 2, ControlCoverage: 0.5, TestEvidence: 0.5,
},
wantLevel: RiskLevelMedium, // 3×2×3×2 = 36 → medium
},
{
name: "ISO high risk",
input: RiskComputeInput{
Severity: 4, Exposure: 3, Probability: 3, Avoidance: 3,
ControlMaturity: 2, ControlCoverage: 0.5, TestEvidence: 0.5,
},
wantLevel: RiskLevelHigh, // 4×3×3×3 = 108 → high
},
{
name: "ISO very high risk",
input: RiskComputeInput{
Severity: 4, Exposure: 4, Probability: 4, Avoidance: 3,
ControlMaturity: 2, ControlCoverage: 0.5, TestEvidence: 0.5,
},
wantLevel: RiskLevelVeryHigh, // 4×4×4×3 = 192 → very_high
},
{
name: "ISO not acceptable",
input: RiskComputeInput{
Severity: 5, Exposure: 5, Probability: 4, Avoidance: 4,
ControlMaturity: 4, ControlCoverage: 1.0, TestEvidence: 1.0,
},
wantLevel: RiskLevelNotAcceptable, // 5×5×4×4 = 400 → not_acceptable
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := e.ComputeRisk(tt.input)
if err != nil {
t.Fatalf("ComputeRisk returned error: %v", err)
}
if result.RiskLevel != tt.wantLevel {
t.Errorf("RiskLevel = %v, want %v (inherent=%v)",
result.RiskLevel, tt.wantLevel, result.InherentRisk)
}
})
}
}
// ============================================================================
// 11. Edge Cases (continued)
// ============================================================================
func TestClampFloat(t *testing.T) {
tests := []struct {
name string

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,8 @@ import (
func TestGetBuiltinHazardLibrary_EntryCount(t *testing.T) {
entries := GetBuiltinHazardLibrary()
// Original 37 + 12 new categories (10+8+6+6+4+5+8+8+5+8+5+6 = 79) = 116
if len(entries) < 100 {
t.Fatalf("GetBuiltinHazardLibrary returned %d entries, want at least 100", len(entries))
if len(entries) < 150 {
t.Fatalf("GetBuiltinHazardLibrary returned %d entries, want at least 150", len(entries))
}
}
@@ -46,33 +45,39 @@ func TestGetBuiltinHazardLibrary_UniqueNonZeroUUIDs(t *testing.T) {
func TestGetBuiltinHazardLibrary_AllCategoriesPresent(t *testing.T) {
entries := GetBuiltinHazardLibrary()
// All 24 categories (12 original + 12 new)
// All expected categories (original AI/SW + extended ISO 12100 physical)
expectedCategories := map[string]bool{
// Original AI/cyber categories
"false_classification": false,
"timing_error": false,
"data_poisoning": false,
"model_drift": false,
"sensor_spoofing": false,
"communication_failure": false,
"unauthorized_access": false,
"firmware_corruption": false,
"safety_boundary_violation": false,
"mode_confusion": false,
"unintended_bias": false,
"update_failure": false,
// New categories
"software_fault": false,
"hmi_error": false,
"mechanical_hazard": false,
"electrical_hazard": false,
"thermal_hazard": false,
"emc_hazard": false,
"configuration_error": false,
"safety_function_failure": false,
"logging_audit_failure": false,
"integration_error": false,
"environmental_hazard": false,
"maintenance_hazard": false,
"timing_error": false,
"data_poisoning": false,
"model_drift": false,
"sensor_spoofing": false,
"communication_failure": false,
"unauthorized_access": false,
"firmware_corruption": false,
"safety_boundary_violation": false,
"mode_confusion": false,
"unintended_bias": false,
"update_failure": false,
// Extended SW/HW categories
"software_fault": false,
"hmi_error": false,
"mechanical_hazard": false,
"electrical_hazard": false,
"thermal_hazard": false,
"emc_hazard": false,
"configuration_error": false,
"safety_function_failure": false,
"logging_audit_failure": false,
"integration_error": false,
"environmental_hazard": false,
"maintenance_hazard": false,
// ISO 12100 physical categories
"pneumatic_hydraulic": false,
"noise_vibration": false,
"ergonomic": false,
"material_environmental": false,
}
for _, e := range entries {
@@ -92,41 +97,29 @@ func TestGetBuiltinHazardLibrary_AllCategoriesPresent(t *testing.T) {
func TestGetBuiltinHazardLibrary_CategoryCounts(t *testing.T) {
entries := GetBuiltinHazardLibrary()
// Original 12 categories: exact counts must remain unchanged
originalCounts := map[string]int{
"false_classification": 4,
"timing_error": 3,
"data_poisoning": 2,
"model_drift": 3,
"sensor_spoofing": 3,
"communication_failure": 3,
"unauthorized_access": 4,
"firmware_corruption": 3,
"safety_boundary_violation": 4,
"mode_confusion": 3,
"unintended_bias": 2,
"update_failure": 3,
}
// New 12 categories: must each have at least 1 entry
newCategories := []string{
"software_fault", "hmi_error", "mechanical_hazard", "electrical_hazard",
"thermal_hazard", "emc_hazard", "configuration_error", "safety_function_failure",
"logging_audit_failure", "integration_error", "environmental_hazard", "maintenance_hazard",
}
actualCounts := make(map[string]int)
for _, e := range entries {
actualCounts[e.Category]++
}
for cat, expected := range originalCounts {
if actualCounts[cat] != expected {
t.Errorf("original category %q: count = %d, want %d", cat, actualCounts[cat], expected)
// Each category must have at least 1 entry
for cat, count := range actualCounts {
if count < 1 {
t.Errorf("category %q: count = %d, want >= 1", cat, count)
}
}
for _, cat := range newCategories {
if actualCounts[cat] < 1 {
t.Errorf("new category %q: count = %d, want >= 1", cat, actualCounts[cat])
// ISO 12100 physical categories must have substantial coverage
minCounts := map[string]int{
"mechanical_hazard": 10,
"electrical_hazard": 6,
"thermal_hazard": 4,
"pneumatic_hydraulic": 6,
"noise_vibration": 4,
}
for cat, minCount := range minCounts {
if actualCounts[cat] < minCount {
t.Errorf("category %q: count = %d, want >= %d", cat, actualCounts[cat], minCount)
}
}
}
@@ -151,6 +144,19 @@ func TestGetBuiltinHazardLibrary_ProbabilityRange(t *testing.T) {
}
}
func TestGetBuiltinHazardLibrary_ExposureAndAvoidanceRange(t *testing.T) {
entries := GetBuiltinHazardLibrary()
for i, e := range entries {
if e.DefaultExposure < 0 || e.DefaultExposure > 5 {
t.Errorf("entries[%d] (%s): DefaultExposure = %d, want 0-5", i, e.Name, e.DefaultExposure)
}
if e.DefaultAvoidance < 0 || e.DefaultAvoidance > 5 {
t.Errorf("entries[%d] (%s): DefaultAvoidance = %d, want 0-5", i, e.Name, e.DefaultAvoidance)
}
}
}
func TestGetBuiltinHazardLibrary_NonEmptyFields(t *testing.T) {
entries := GetBuiltinHazardLibrary()
@@ -164,9 +170,6 @@ func TestGetBuiltinHazardLibrary_NonEmptyFields(t *testing.T) {
if len(e.ApplicableComponentTypes) == 0 {
t.Errorf("entries[%d] (%s): ApplicableComponentTypes is empty", i, e.Name)
}
if len(e.RegulationReferences) == 0 {
t.Errorf("entries[%d] (%s): RegulationReferences is empty", i, e.Name)
}
}
}
@@ -178,8 +181,8 @@ func TestHazardUUID_Deterministic(t *testing.T) {
{"false_classification", 1},
{"timing_error", 2},
{"data_poisoning", 1},
{"update_failure", 3},
{"mode_confusion", 1},
{"mechanical_hazard", 7},
{"pneumatic_hydraulic", 1},
}
for _, tt := range tests {
@@ -206,8 +209,8 @@ func TestHazardUUID_DifferentInputsProduceDifferentUUIDs(t *testing.T) {
}{
{"false_classification", 1, "false_classification", 2},
{"false_classification", 1, "timing_error", 1},
{"data_poisoning", 1, "data_poisoning", 2},
{"mode_confusion", 1, "mode_confusion", 3},
{"mechanical_hazard", 7, "mechanical_hazard", 8},
{"pneumatic_hydraulic", 1, "noise_vibration", 1},
}
for _, tt := range tests {
@@ -265,6 +268,8 @@ func TestGetBuiltinHazardLibrary_ApplicableComponentTypesAreValid(t *testing.T)
string(ComponentTypeActuator): true,
string(ComponentTypeController): true,
string(ComponentTypeNetwork): true,
string(ComponentTypeMechanical): true,
string(ComponentTypeElectrical): true,
string(ComponentTypeOther): true,
}
@@ -277,26 +282,6 @@ func TestGetBuiltinHazardLibrary_ApplicableComponentTypesAreValid(t *testing.T)
}
}
func TestGetBuiltinHazardLibrary_UUIDsMatchExpected(t *testing.T) {
// Verify the first entry of each category has the expected UUID
// based on the deterministic hazardUUID function.
entries := GetBuiltinHazardLibrary()
categoryFirstSeen := make(map[string]uuid.UUID)
for _, e := range entries {
if _, exists := categoryFirstSeen[e.Category]; !exists {
categoryFirstSeen[e.Category] = e.ID
}
}
for cat, actualID := range categoryFirstSeen {
expectedID := hazardUUID(cat, 1)
if actualID != expectedID {
t.Errorf("first entry of category %q: ID = %s, want %s", cat, actualID, expectedID)
}
}
}
func TestGetBuiltinHazardLibrary_ConsistentAcrossCalls(t *testing.T) {
entries1 := GetBuiltinHazardLibrary()
entries2 := GetBuiltinHazardLibrary()
@@ -312,8 +297,90 @@ func TestGetBuiltinHazardLibrary_ConsistentAcrossCalls(t *testing.T) {
if entries1[i].Name != entries2[i].Name {
t.Errorf("entries[%d]: Name mismatch across calls: %q vs %q", i, entries1[i].Name, entries2[i].Name)
}
if entries1[i].Category != entries2[i].Category {
t.Errorf("entries[%d]: Category mismatch across calls: %q vs %q", i, entries1[i].Category, entries2[i].Category)
}
}
// TestGetProtectiveMeasureLibrary_EntryCount verifies the protective measures library size
func TestGetProtectiveMeasureLibrary_EntryCount(t *testing.T) {
entries := GetProtectiveMeasureLibrary()
if len(entries) < 150 {
t.Fatalf("GetProtectiveMeasureLibrary returned %d entries, want at least 150", len(entries))
}
}
// TestGetProtectiveMeasureLibrary_AllTypesPresent verifies all 3 reduction types exist
func TestGetProtectiveMeasureLibrary_AllTypesPresent(t *testing.T) {
entries := GetProtectiveMeasureLibrary()
typeCounts := map[string]int{}
for _, e := range entries {
typeCounts[e.ReductionType]++
}
for _, rt := range []string{"design", "information"} {
if typeCounts[rt] < 10 {
t.Errorf("reduction type %q: count = %d, want >= 10", rt, typeCounts[rt])
}
}
// Accept both "protection" and "protective" naming
protCount := typeCounts["protection"] + typeCounts["protective"]
if protCount < 10 {
t.Errorf("reduction type protection/protective: count = %d, want >= 10", protCount)
}
}
// TestGetProtectiveMeasureLibrary_UniqueIDs verifies all measure IDs are unique
func TestGetProtectiveMeasureLibrary_UniqueIDs(t *testing.T) {
entries := GetProtectiveMeasureLibrary()
seen := make(map[string]string)
for i, e := range entries {
if e.ID == "" {
t.Errorf("entries[%d] (%s): ID is empty", i, e.Name)
continue
}
if prev, exists := seen[e.ID]; exists {
t.Errorf("entries[%d] (%s): duplicate ID %q, same as %q", i, e.Name, e.ID, prev)
}
seen[e.ID] = e.Name
}
}
// TestGetProtectiveMeasureLibrary_NonEmptyFields verifies required fields are filled
func TestGetProtectiveMeasureLibrary_NonEmptyFields(t *testing.T) {
entries := GetProtectiveMeasureLibrary()
for i, e := range entries {
if e.Name == "" {
t.Errorf("entries[%d]: Name is empty", i)
}
if e.Description == "" {
t.Errorf("entries[%d] (%s): Description is empty", i, e.Name)
}
if e.ReductionType == "" {
t.Errorf("entries[%d] (%s): ReductionType is empty", i, e.Name)
}
}
}
// TestGetProtectiveMeasureLibrary_ValidReductionTypes verifies reduction types are valid
func TestGetProtectiveMeasureLibrary_ValidReductionTypes(t *testing.T) {
entries := GetProtectiveMeasureLibrary()
validTypes := map[string]bool{"design": true, "protection": true, "protective": true, "information": true}
for i, e := range entries {
if !validTypes[e.ReductionType] {
t.Errorf("entries[%d] (%s): invalid ReductionType %q", i, e.Name, e.ReductionType)
}
}
}
// TestGetControlsLibrary_EntryCount verifies the controls library size
func TestGetControlsLibrary_EntryCount(t *testing.T) {
entries := GetControlsLibrary()
if len(entries) < 30 {
t.Fatalf("GetControlsLibrary returned %d entries, want at least 30", len(entries))
}
}

View File

@@ -38,6 +38,8 @@ const (
ComponentTypeActuator ComponentType = "actuator"
ComponentTypeController ComponentType = "controller"
ComponentTypeNetwork ComponentType = "network"
ComponentTypeMechanical ComponentType = "mechanical"
ComponentTypeElectrical ComponentType = "electrical"
ComponentTypeOther ComponentType = "other"
)
@@ -75,11 +77,13 @@ const (
type RiskLevel string
const (
RiskLevelCritical RiskLevel = "critical"
RiskLevelHigh RiskLevel = "high"
RiskLevelMedium RiskLevel = "medium"
RiskLevelLow RiskLevel = "low"
RiskLevelNegligible RiskLevel = "negligible"
RiskLevelNotAcceptable RiskLevel = "not_acceptable" // ISO 12100 mode: > 300
RiskLevelVeryHigh RiskLevel = "very_high" // ISO 12100 mode: 151-300
RiskLevelCritical RiskLevel = "critical"
RiskLevelHigh RiskLevel = "high"
RiskLevelMedium RiskLevel = "medium"
RiskLevelLow RiskLevel = "low"
RiskLevelNegligible RiskLevel = "negligible"
)
// ReductionType represents the type of risk reduction measure
@@ -105,10 +109,20 @@ const (
type VerificationMethod string
const (
VerificationMethodTest VerificationMethod = "test"
VerificationMethodAnalysis VerificationMethod = "analysis"
VerificationMethodInspection VerificationMethod = "inspection"
VerificationMethodReview VerificationMethod = "review"
VerificationMethodTest VerificationMethod = "test"
VerificationMethodAnalysis VerificationMethod = "analysis"
VerificationMethodInspection VerificationMethod = "inspection"
VerificationMethodReview VerificationMethod = "review"
VerificationMethodDesignReview VerificationMethod = "design_review"
VerificationMethodCalculation VerificationMethod = "calculation"
VerificationMethodTestReport VerificationMethod = "test_report"
VerificationMethodValidation VerificationMethod = "validation"
VerificationMethodElectricalTest VerificationMethod = "electrical_test"
VerificationMethodSoftwareTest VerificationMethod = "software_test"
VerificationMethodPenetrationTest VerificationMethod = "penetration_test"
VerificationMethodAcceptanceProtocol VerificationMethod = "acceptance_protocol"
VerificationMethodUserTest VerificationMethod = "user_test"
VerificationMethodDocRelease VerificationMethod = "documentation_release"
)
// TechFileSectionStatus represents the status of a technical file section
@@ -143,6 +157,48 @@ const (
AuditActionVerify AuditAction = "verify"
)
// LifecyclePhase represents a machine lifecycle phase per ISO 12100 methodology
type LifecyclePhase string
const (
LPTransport LifecyclePhase = "transport"
LPStorage LifecyclePhase = "storage"
LPAssembly LifecyclePhase = "assembly"
LPInstallation LifecyclePhase = "installation"
LPCommissioning LifecyclePhase = "commissioning"
LPParameterization LifecyclePhase = "parameterization"
LPSetup LifecyclePhase = "setup"
LPNormalOperation LifecyclePhase = "normal_operation"
LPAutoOperation LifecyclePhase = "automatic_operation"
LPManualOperation LifecyclePhase = "manual_operation"
LPTeachMode LifecyclePhase = "teach_mode"
LPProductionStart LifecyclePhase = "production_start"
LPProductionStop LifecyclePhase = "production_stop"
LPProcessMonitoring LifecyclePhase = "process_monitoring"
LPCleaning LifecyclePhase = "cleaning"
LPMaintenance LifecyclePhase = "maintenance"
LPInspection LifecyclePhase = "inspection"
LPCalibration LifecyclePhase = "calibration"
LPFaultClearing LifecyclePhase = "fault_clearing"
LPRepair LifecyclePhase = "repair"
LPChangeover LifecyclePhase = "changeover"
LPSoftwareUpdate LifecyclePhase = "software_update"
LPRemoteMaintenance LifecyclePhase = "remote_maintenance"
LPDecommissioning LifecyclePhase = "decommissioning"
LPDisposal LifecyclePhase = "disposal"
)
// ReviewStatus represents the review state of a hazard assessment
type ReviewStatus string
const (
ReviewStatusDraft ReviewStatus = "draft"
ReviewStatusInReview ReviewStatus = "in_review"
ReviewStatusReviewed ReviewStatus = "reviewed"
ReviewStatusApproved ReviewStatus = "approved"
ReviewStatusRejected ReviewStatus = "rejected"
)
// ============================================================================
// Main Entities
// ============================================================================
@@ -203,13 +259,24 @@ type RegulatoryClassification struct {
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"`
IsBuiltin bool `json:"is_builtin"`
TenantID *uuid.UUID `json:"tenant_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
@@ -225,7 +292,16 @@ type Hazard struct {
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"`
}
@@ -397,6 +473,14 @@ type CreateHazardRequest struct {
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
@@ -467,6 +551,8 @@ type ProjectDetailResponse struct {
// 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"`
@@ -476,6 +562,54 @@ type RiskSummaryResponse struct {
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"`
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"`
}
// 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"`

View File

@@ -554,7 +554,16 @@ func (s *Store) CreateHazard(ctx context.Context, req CreateHazardRequest) (*Haz
Description: req.Description,
Scenario: req.Scenario,
Category: req.Category,
SubCategory: req.SubCategory,
Status: HazardStatusIdentified,
MachineModule: req.MachineModule,
Function: req.Function,
LifecyclePhase: req.LifecyclePhase,
HazardousZone: req.HazardousZone,
TriggerEvent: req.TriggerEvent,
AffectedPerson: req.AffectedPerson,
PossibleHarm: req.PossibleHarm,
ReviewStatus: ReviewStatusDraft,
CreatedAt: time.Now().UTC(),
UpdatedAt: time.Now().UTC(),
}
@@ -562,16 +571,22 @@ func (s *Store) CreateHazard(ctx context.Context, req CreateHazardRequest) (*Haz
_, err := s.pool.Exec(ctx, `
INSERT INTO iace_hazards (
id, project_id, component_id, library_hazard_id,
name, description, scenario, category, status,
name, description, scenario, category, sub_category, status,
machine_module, function, lifecycle_phase, hazardous_zone,
trigger_event, affected_person, possible_harm, review_status,
created_at, updated_at
) VALUES (
$1, $2, $3, $4,
$5, $6, $7, $8, $9,
$10, $11
$5, $6, $7, $8, $9, $10,
$11, $12, $13, $14,
$15, $16, $17, $18,
$19, $20
)
`,
h.ID, h.ProjectID, h.ComponentID, h.LibraryHazardID,
h.Name, h.Description, h.Scenario, h.Category, string(h.Status),
h.Name, h.Description, h.Scenario, h.Category, h.SubCategory, string(h.Status),
h.MachineModule, h.Function, h.LifecyclePhase, h.HazardousZone,
h.TriggerEvent, h.AffectedPerson, h.PossibleHarm, string(h.ReviewStatus),
h.CreatedAt, h.UpdatedAt,
)
if err != nil {
@@ -584,17 +599,21 @@ func (s *Store) CreateHazard(ctx context.Context, req CreateHazardRequest) (*Haz
// GetHazard retrieves a hazard by ID
func (s *Store) GetHazard(ctx context.Context, id uuid.UUID) (*Hazard, error) {
var h Hazard
var status string
var status, reviewStatus string
err := s.pool.QueryRow(ctx, `
SELECT
id, project_id, component_id, library_hazard_id,
name, description, scenario, category, status,
name, description, scenario, category, sub_category, status,
machine_module, function, lifecycle_phase, hazardous_zone,
trigger_event, affected_person, possible_harm, review_status,
created_at, updated_at
FROM iace_hazards WHERE id = $1
`, id).Scan(
&h.ID, &h.ProjectID, &h.ComponentID, &h.LibraryHazardID,
&h.Name, &h.Description, &h.Scenario, &h.Category, &status,
&h.Name, &h.Description, &h.Scenario, &h.Category, &h.SubCategory, &status,
&h.MachineModule, &h.Function, &h.LifecyclePhase, &h.HazardousZone,
&h.TriggerEvent, &h.AffectedPerson, &h.PossibleHarm, &reviewStatus,
&h.CreatedAt, &h.UpdatedAt,
)
if err == pgx.ErrNoRows {
@@ -605,6 +624,7 @@ func (s *Store) GetHazard(ctx context.Context, id uuid.UUID) (*Hazard, error) {
}
h.Status = HazardStatus(status)
h.ReviewStatus = ReviewStatus(reviewStatus)
return &h, nil
}
@@ -613,7 +633,9 @@ func (s *Store) ListHazards(ctx context.Context, projectID uuid.UUID) ([]Hazard,
rows, err := s.pool.Query(ctx, `
SELECT
id, project_id, component_id, library_hazard_id,
name, description, scenario, category, status,
name, description, scenario, category, sub_category, status,
machine_module, function, lifecycle_phase, hazardous_zone,
trigger_event, affected_person, possible_harm, review_status,
created_at, updated_at
FROM iace_hazards WHERE project_id = $1
ORDER BY created_at ASC
@@ -626,11 +648,13 @@ func (s *Store) ListHazards(ctx context.Context, projectID uuid.UUID) ([]Hazard,
var hazards []Hazard
for rows.Next() {
var h Hazard
var status string
var status, reviewStatus string
err := rows.Scan(
&h.ID, &h.ProjectID, &h.ComponentID, &h.LibraryHazardID,
&h.Name, &h.Description, &h.Scenario, &h.Category, &status,
&h.Name, &h.Description, &h.Scenario, &h.Category, &h.SubCategory, &status,
&h.MachineModule, &h.Function, &h.LifecyclePhase, &h.HazardousZone,
&h.TriggerEvent, &h.AffectedPerson, &h.PossibleHarm, &reviewStatus,
&h.CreatedAt, &h.UpdatedAt,
)
if err != nil {
@@ -638,6 +662,7 @@ func (s *Store) ListHazards(ctx context.Context, projectID uuid.UUID) ([]Hazard,
}
h.Status = HazardStatus(status)
h.ReviewStatus = ReviewStatus(reviewStatus)
hazards = append(hazards, h)
}
@@ -654,20 +679,19 @@ func (s *Store) UpdateHazard(ctx context.Context, id uuid.UUID, updates map[stri
args := []interface{}{id}
argIdx := 2
allowedFields := map[string]bool{
"name": true, "description": true, "scenario": true, "category": true,
"sub_category": true, "status": true, "component_id": true,
"machine_module": true, "function": true, "lifecycle_phase": true,
"hazardous_zone": true, "trigger_event": true, "affected_person": true,
"possible_harm": true, "review_status": true,
}
for key, val := range updates {
switch key {
case "name", "description", "scenario", "category":
if allowedFields[key] {
query += fmt.Sprintf(", %s = $%d", key, argIdx)
args = append(args, val)
argIdx++
case "status":
query += fmt.Sprintf(", status = $%d", argIdx)
args = append(args, val)
argIdx++
case "component_id":
query += fmt.Sprintf(", component_id = $%d", argIdx)
args = append(args, val)
argIdx++
}
}
@@ -1591,10 +1615,20 @@ func (s *Store) ListAuditTrail(ctx context.Context, projectID uuid.UUID) ([]Audi
func (s *Store) ListHazardLibrary(ctx context.Context, category string, componentType string) ([]HazardLibraryEntry, error) {
query := `
SELECT
id, category, name, description,
id, category, COALESCE(sub_category, ''), name, description,
default_severity, default_probability,
COALESCE(default_exposure, 3), COALESCE(default_avoidance, 3),
applicable_component_types, regulation_references,
suggested_mitigations, is_builtin, tenant_id,
suggested_mitigations,
COALESCE(typical_causes, '[]'::jsonb),
COALESCE(typical_harm, ''),
COALESCE(relevant_lifecycle_phases, '[]'::jsonb),
COALESCE(recommended_measures_design, '[]'::jsonb),
COALESCE(recommended_measures_technical, '[]'::jsonb),
COALESCE(recommended_measures_information, '[]'::jsonb),
COALESCE(suggested_evidence, '[]'::jsonb),
COALESCE(related_keywords, '[]'::jsonb),
is_builtin, tenant_id,
created_at
FROM iace_hazard_library WHERE 1=1`
@@ -1625,12 +1659,18 @@ func (s *Store) ListHazardLibrary(ctx context.Context, category string, componen
for rows.Next() {
var e HazardLibraryEntry
var applicableComponentTypes, regulationReferences, suggestedMitigations []byte
var typicalCauses, relevantPhases, measuresDesign, measuresTechnical, measuresInfo, evidence, keywords []byte
err := rows.Scan(
&e.ID, &e.Category, &e.Name, &e.Description,
&e.ID, &e.Category, &e.SubCategory, &e.Name, &e.Description,
&e.DefaultSeverity, &e.DefaultProbability,
&e.DefaultExposure, &e.DefaultAvoidance,
&applicableComponentTypes, &regulationReferences,
&suggestedMitigations, &e.IsBuiltin, &e.TenantID,
&suggestedMitigations,
&typicalCauses, &e.TypicalHarm, &relevantPhases,
&measuresDesign, &measuresTechnical, &measuresInfo,
&evidence, &keywords,
&e.IsBuiltin, &e.TenantID,
&e.CreatedAt,
)
if err != nil {
@@ -1640,6 +1680,13 @@ func (s *Store) ListHazardLibrary(ctx context.Context, category string, componen
json.Unmarshal(applicableComponentTypes, &e.ApplicableComponentTypes)
json.Unmarshal(regulationReferences, &e.RegulationReferences)
json.Unmarshal(suggestedMitigations, &e.SuggestedMitigations)
json.Unmarshal(typicalCauses, &e.TypicalCauses)
json.Unmarshal(relevantPhases, &e.RelevantLifecyclePhases)
json.Unmarshal(measuresDesign, &e.RecommendedMeasuresDesign)
json.Unmarshal(measuresTechnical, &e.RecommendedMeasuresTechnical)
json.Unmarshal(measuresInfo, &e.RecommendedMeasuresInformation)
json.Unmarshal(evidence, &e.SuggestedEvidence)
json.Unmarshal(keywords, &e.RelatedKeywords)
if e.ApplicableComponentTypes == nil {
e.ApplicableComponentTypes = []string{}
@@ -1658,6 +1705,9 @@ func (s *Store) ListHazardLibrary(ctx context.Context, category string, componen
func (s *Store) GetHazardLibraryEntry(ctx context.Context, id uuid.UUID) (*HazardLibraryEntry, error) {
var e HazardLibraryEntry
var applicableComponentTypes, regulationReferences, suggestedMitigations []byte
var typicalCauses, relevantLifecyclePhases []byte
var recommendedMeasuresDesign, recommendedMeasuresTechnical, recommendedMeasuresInformation []byte
var suggestedEvidence, relatedKeywords []byte
err := s.pool.QueryRow(ctx, `
SELECT
@@ -1665,7 +1715,18 @@ func (s *Store) GetHazardLibraryEntry(ctx context.Context, id uuid.UUID) (*Hazar
default_severity, default_probability,
applicable_component_types, regulation_references,
suggested_mitigations, is_builtin, tenant_id,
created_at
created_at,
COALESCE(sub_category, ''),
COALESCE(default_exposure, 3),
COALESCE(default_avoidance, 3),
COALESCE(typical_causes, '[]'),
COALESCE(typical_harm, ''),
COALESCE(relevant_lifecycle_phases, '[]'),
COALESCE(recommended_measures_design, '[]'),
COALESCE(recommended_measures_technical, '[]'),
COALESCE(recommended_measures_information, '[]'),
COALESCE(suggested_evidence, '[]'),
COALESCE(related_keywords, '[]')
FROM iace_hazard_library WHERE id = $1
`, id).Scan(
&e.ID, &e.Category, &e.Name, &e.Description,
@@ -1673,6 +1734,12 @@ func (s *Store) GetHazardLibraryEntry(ctx context.Context, id uuid.UUID) (*Hazar
&applicableComponentTypes, &regulationReferences,
&suggestedMitigations, &e.IsBuiltin, &e.TenantID,
&e.CreatedAt,
&e.SubCategory,
&e.DefaultExposure, &e.DefaultAvoidance,
&typicalCauses, &e.TypicalHarm,
&relevantLifecyclePhases,
&recommendedMeasuresDesign, &recommendedMeasuresTechnical, &recommendedMeasuresInformation,
&suggestedEvidence, &relatedKeywords,
)
if err == pgx.ErrNoRows {
return nil, nil
@@ -1684,6 +1751,13 @@ func (s *Store) GetHazardLibraryEntry(ctx context.Context, id uuid.UUID) (*Hazar
json.Unmarshal(applicableComponentTypes, &e.ApplicableComponentTypes)
json.Unmarshal(regulationReferences, &e.RegulationReferences)
json.Unmarshal(suggestedMitigations, &e.SuggestedMitigations)
json.Unmarshal(typicalCauses, &e.TypicalCauses)
json.Unmarshal(relevantLifecyclePhases, &e.RelevantLifecyclePhases)
json.Unmarshal(recommendedMeasuresDesign, &e.RecommendedMeasuresDesign)
json.Unmarshal(recommendedMeasuresTechnical, &e.RecommendedMeasuresTechnical)
json.Unmarshal(recommendedMeasuresInformation, &e.RecommendedMeasuresInformation)
json.Unmarshal(suggestedEvidence, &e.SuggestedEvidence)
json.Unmarshal(relatedKeywords, &e.RelatedKeywords)
if e.ApplicableComponentTypes == nil {
e.ApplicableComponentTypes = []string{}
@@ -1731,6 +1805,10 @@ func (s *Store) GetRiskSummary(ctx context.Context, projectID uuid.UUID) (*RiskS
}
switch latest.RiskLevel {
case RiskLevelNotAcceptable:
summary.NotAcceptable++
case RiskLevelVeryHigh:
summary.VeryHigh++
case RiskLevelCritical:
summary.Critical++
case RiskLevelHigh:
@@ -1761,6 +1839,10 @@ func (s *Store) GetRiskSummary(ctx context.Context, projectID uuid.UUID) (*RiskS
// riskLevelSeverity returns a numeric severity for risk level comparison
func riskLevelSeverity(rl RiskLevel) int {
switch rl {
case RiskLevelNotAcceptable:
return 7
case RiskLevelVeryHigh:
return 6
case RiskLevelCritical:
return 5
case RiskLevelHigh:
@@ -1775,3 +1857,72 @@ func riskLevelSeverity(rl RiskLevel) int {
return 0
}
}
// ListLifecyclePhases returns all 12 lifecycle phases with DE/EN labels
func (s *Store) ListLifecyclePhases(ctx context.Context) ([]LifecyclePhaseInfo, error) {
rows, err := s.pool.Query(ctx, `
SELECT id, label_de, label_en, sort_order
FROM iace_lifecycle_phases
ORDER BY sort_order ASC
`)
if err != nil {
return nil, fmt.Errorf("list lifecycle phases: %w", err)
}
defer rows.Close()
var phases []LifecyclePhaseInfo
for rows.Next() {
var p LifecyclePhaseInfo
if err := rows.Scan(&p.ID, &p.LabelDE, &p.LabelEN, &p.Sort); err != nil {
return nil, fmt.Errorf("list lifecycle phases scan: %w", err)
}
phases = append(phases, p)
}
return phases, nil
}
// ListRoles returns all affected person roles from the reference table
func (s *Store) ListRoles(ctx context.Context) ([]RoleInfo, error) {
rows, err := s.pool.Query(ctx, `
SELECT id, label_de, label_en, sort_order
FROM iace_roles
ORDER BY sort_order ASC
`)
if err != nil {
return nil, fmt.Errorf("list roles: %w", err)
}
defer rows.Close()
var roles []RoleInfo
for rows.Next() {
var r RoleInfo
if err := rows.Scan(&r.ID, &r.LabelDE, &r.LabelEN, &r.Sort); err != nil {
return nil, fmt.Errorf("list roles scan: %w", err)
}
roles = append(roles, r)
}
return roles, nil
}
// ListEvidenceTypes returns all evidence types from the reference table
func (s *Store) ListEvidenceTypes(ctx context.Context) ([]EvidenceTypeInfo, error) {
rows, err := s.pool.Query(ctx, `
SELECT id, category, label_de, label_en, sort_order
FROM iace_evidence_types
ORDER BY sort_order ASC
`)
if err != nil {
return nil, fmt.Errorf("list evidence types: %w", err)
}
defer rows.Close()
var types []EvidenceTypeInfo
for rows.Next() {
var e EvidenceTypeInfo
if err := rows.Scan(&e.ID, &e.Category, &e.LabelDE, &e.LabelEN, &e.Sort); err != nil {
return nil, fmt.Errorf("list evidence types scan: %w", err)
}
types = append(types, e)
}
return types, nil
}

View File

@@ -0,0 +1,58 @@
-- Migration 018: ISO 12100 Machine Risk Model Extension for IACE
-- Adds lifecycle phases, extended hazard fields, and protective measures metadata.
-- ============================================================================
-- 1. Extend iace_hazards with ISO 12100 fields
-- ============================================================================
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS machine_module TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS function TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS lifecycle_phase TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS hazardous_zone TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS trigger_event TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS affected_person TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS possible_harm TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS sub_category TEXT DEFAULT '';
ALTER TABLE iace_hazards ADD COLUMN IF NOT EXISTS review_status TEXT DEFAULT 'draft';
-- ============================================================================
-- 2. Extend iace_hazard_library with ISO 12100 metadata
-- ============================================================================
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS sub_category TEXT DEFAULT '';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS default_exposure INT DEFAULT 3;
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS default_avoidance INT DEFAULT 3;
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS typical_causes JSONB DEFAULT '[]';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS typical_harm TEXT DEFAULT '';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS relevant_lifecycle_phases JSONB DEFAULT '[]';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS recommended_measures_design JSONB DEFAULT '[]';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS recommended_measures_technical JSONB DEFAULT '[]';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS recommended_measures_information JSONB DEFAULT '[]';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS suggested_evidence JSONB DEFAULT '[]';
ALTER TABLE iace_hazard_library ADD COLUMN IF NOT EXISTS related_keywords JSONB DEFAULT '[]';
-- ============================================================================
-- 3. Reference table: Lifecycle phases (DE/EN labels)
-- ============================================================================
CREATE TABLE IF NOT EXISTS iace_lifecycle_phases (
id TEXT PRIMARY KEY,
label_de TEXT NOT NULL,
label_en TEXT NOT NULL,
sort_order INT NOT NULL DEFAULT 0
);
INSERT INTO iace_lifecycle_phases (id, label_de, label_en, sort_order) VALUES
('transport', 'Transport', 'Transport', 1),
('assembly', 'Montage', 'Assembly', 2),
('commissioning', 'Inbetriebnahme', 'Commissioning', 3),
('setup_teach', 'Einrichten / Teach', 'Setup / Teach', 4),
('normal_operation', 'Normalbetrieb', 'Normal Operation', 5),
('special_operation', 'Sonderbetrieb', 'Special Operation', 6),
('cleaning', 'Reinigung', 'Cleaning', 7),
('maintenance', 'Wartung', 'Maintenance', 8),
('fault_clearing', 'Stoerungsbeseitigung', 'Fault Clearing', 9),
('changeover', 'Umruestung', 'Changeover', 10),
('decommissioning', 'Ausserbetriebnahme', 'Decommissioning', 11),
('disposal', 'Demontage / Entsorgung', 'Dismantling / Disposal', 12)
ON CONFLICT (id) DO NOTHING;

View File

@@ -0,0 +1,149 @@
-- Migration 019: Extended IACE reference libraries
-- Adds 25 lifecycle phases, 20 roles, 50 evidence types.
-- All content is original (not derived from normative text).
-- ============================================================================
-- 1. Expand lifecycle phases from 12 to 25
-- ============================================================================
INSERT INTO iace_lifecycle_phases (id, label_de, label_en, sort_order) VALUES
('storage', 'Lagerung', 'Storage', 2),
('installation', 'Installation', 'Installation', 4),
('parameterization', 'Parametrierung', 'Parameterization', 6),
('setup', 'Einrichten / Setup', 'Setup', 7),
('automatic_operation', 'Automatikbetrieb', 'Automatic Operation', 9),
('manual_operation', 'Handbetrieb', 'Manual Operation', 10),
('teach_mode', 'Teach-Modus', 'Teach Mode', 11),
('production_start', 'Produktionsstart', 'Production Start', 12),
('production_stop', 'Produktionsstopp', 'Production Stop', 13),
('process_monitoring', 'Prozessueberwachung', 'Process Monitoring', 14),
('inspection', 'Inspektion', 'Inspection', 17),
('calibration', 'Kalibrierung', 'Calibration', 18),
('repair', 'Reparatur', 'Repair', 20),
('software_update', 'Software-Update', 'Software Update', 22),
('remote_maintenance', 'Fernwartung', 'Remote Maintenance', 23)
ON CONFLICT (id) DO NOTHING;
-- Update sort_order for existing phases to interleave correctly
UPDATE iace_lifecycle_phases SET sort_order = 1 WHERE id = 'transport';
UPDATE iace_lifecycle_phases SET sort_order = 3 WHERE id = 'assembly';
UPDATE iace_lifecycle_phases SET sort_order = 5 WHERE id = 'commissioning';
UPDATE iace_lifecycle_phases SET sort_order = 8 WHERE id = 'normal_operation';
UPDATE iace_lifecycle_phases SET sort_order = 15 WHERE id = 'cleaning';
UPDATE iace_lifecycle_phases SET sort_order = 16 WHERE id = 'maintenance';
UPDATE iace_lifecycle_phases SET sort_order = 19 WHERE id = 'fault_clearing';
UPDATE iace_lifecycle_phases SET sort_order = 21 WHERE id = 'changeover';
UPDATE iace_lifecycle_phases SET sort_order = 24 WHERE id = 'decommissioning';
UPDATE iace_lifecycle_phases SET sort_order = 25 WHERE id = 'disposal';
-- Remove old phases that are now replaced by more granular ones
-- setup_teach is split into 'setup' and 'teach_mode'
-- special_operation is covered by manual_operation + teach_mode
DELETE FROM iace_lifecycle_phases WHERE id = 'setup_teach';
DELETE FROM iace_lifecycle_phases WHERE id = 'special_operation';
-- ============================================================================
-- 2. Roles / affected person groups (20)
-- ============================================================================
CREATE TABLE IF NOT EXISTS iace_roles (
id TEXT PRIMARY KEY,
label_de TEXT NOT NULL,
label_en TEXT NOT NULL,
sort_order INT NOT NULL DEFAULT 0
);
INSERT INTO iace_roles (id, label_de, label_en, sort_order) VALUES
('operator', 'Maschinenbediener', 'Machine Operator', 1),
('setter', 'Einrichter', 'Setter', 2),
('maintenance_tech', 'Wartungstechniker', 'Maintenance Technician', 3),
('service_tech', 'Servicetechniker', 'Service Technician', 4),
('cleaning_staff', 'Reinigungspersonal', 'Cleaning Staff', 5),
('production_manager', 'Produktionsleiter', 'Production Manager', 6),
('safety_officer', 'Sicherheitsbeauftragter', 'Safety Officer', 7),
('electrician', 'Elektriker', 'Electrician', 8),
('software_engineer', 'Softwareingenieur', 'Software Engineer', 9),
('maintenance_manager', 'Instandhaltungsleiter', 'Maintenance Manager', 10),
('plant_operator', 'Anlagenfahrer', 'Plant Operator', 11),
('qa_inspector', 'Qualitaetssicherung', 'Quality Assurance', 12),
('logistics_staff', 'Logistikpersonal', 'Logistics Staff', 13),
('subcontractor', 'Fremdfirma / Subunternehmer', 'Subcontractor', 14),
('visitor', 'Besucher', 'Visitor', 15),
('auditor', 'Auditor', 'Auditor', 16),
('it_admin', 'IT-Administrator', 'IT Administrator', 17),
('remote_service', 'Fernwartungsdienst', 'Remote Service', 18),
('plant_owner', 'Betreiber', 'Plant Owner / Operator', 19),
('emergency_responder', 'Notfallpersonal', 'Emergency Responder', 20)
ON CONFLICT (id) DO NOTHING;
-- ============================================================================
-- 3. Evidence types (50)
-- ============================================================================
CREATE TABLE IF NOT EXISTS iace_evidence_types (
id TEXT PRIMARY KEY,
category TEXT NOT NULL,
label_de TEXT NOT NULL,
label_en TEXT NOT NULL,
sort_order INT NOT NULL DEFAULT 0
);
INSERT INTO iace_evidence_types (id, category, label_de, label_en, sort_order) VALUES
-- Engineering evidence
('E01', 'engineering', 'Konstruktionsreview', 'Design Review', 1),
('E02', 'engineering', 'Sicherheitskonzept', 'Safety Concept', 2),
('E03', 'engineering', 'Gefaehrdungsanalyse', 'Hazard Analysis', 3),
('E04', 'engineering', 'Berechnung Sicherheitsabstand', 'Safety Distance Calculation', 4),
('E05', 'engineering', 'Festigkeitsnachweis', 'Strength Verification', 5),
('E06', 'engineering', 'Risikoanalysebericht', 'Risk Analysis Report', 6),
('E07', 'engineering', 'Architekturdiagramm', 'Architecture Diagram', 7),
('E08', 'engineering', 'Software-Designreview', 'Software Design Review', 8),
('E09', 'engineering', 'Code Review', 'Code Review', 9),
('E10', 'engineering', 'Sicherheitsanforderungsdokument', 'Safety Requirements Document', 10),
-- Test evidence
('E11', 'test', 'Funktionstest', 'Functional Test', 11),
('E12', 'test', 'Integrationstest', 'Integration Test', 12),
('E13', 'test', 'Systemtest', 'System Test', 13),
('E14', 'test', 'Sicherheitsfunktionstest', 'Safety Function Test', 14),
('E15', 'test', 'Not-Halt Test', 'Emergency Stop Test', 15),
('E16', 'test', 'Verriegelungstest', 'Interlock Test', 16),
('E17', 'test', 'Fault Injection Test', 'Fault Injection Test', 17),
('E18', 'test', 'Simulationstest', 'Simulation Test', 18),
('E19', 'test', 'Lasttest', 'Load Test', 19),
('E20', 'test', 'Stresstest', 'Stress Test', 20),
-- Electrical testing
('E21', 'electrical', 'Schutzleiterpruefung', 'Protective Conductor Test', 21),
('E22', 'electrical', 'Isolationsmessung', 'Insulation Measurement', 22),
('E23', 'electrical', 'Hochspannungspruefung', 'High Voltage Test', 23),
('E24', 'electrical', 'Kurzschlusspruefung', 'Short Circuit Test', 24),
('E25', 'electrical', 'Erdungsmessung', 'Grounding Measurement', 25),
-- Cyber / Software
('E26', 'cyber', 'Penetration Test', 'Penetration Test', 26),
('E27', 'cyber', 'Vulnerability Scan', 'Vulnerability Scan', 27),
('E28', 'cyber', 'SBOM Pruefung', 'SBOM Review', 28),
('E29', 'cyber', 'Dependency Scan', 'Dependency Scan', 29),
('E30', 'cyber', 'Update-Signaturpruefung', 'Update Signature Verification', 30),
-- Documentation evidence
('E31', 'documentation', 'Betriebsanleitung', 'Operating Manual', 31),
('E32', 'documentation', 'Wartungsanleitung', 'Maintenance Manual', 32),
('E33', 'documentation', 'Sicherheitsanweisung', 'Safety Instruction', 33),
('E34', 'documentation', 'Schulungsnachweis', 'Training Record', 34),
('E35', 'documentation', 'Risikoabnahmeprotokoll', 'Risk Acceptance Protocol', 35),
-- Process evidence
('E36', 'process', 'Freigabedokument', 'Release Document', 36),
('E37', 'process', 'Aenderungsprotokoll', 'Change Protocol', 37),
('E38', 'process', 'Auditbericht', 'Audit Report', 38),
('E39', 'process', 'Abnahmeprotokoll', 'Acceptance Protocol', 39),
('E40', 'process', 'Pruefprotokoll', 'Test Protocol', 40),
-- Operational evidence
('E41', 'operational', 'Monitoring-Logs', 'Monitoring Logs', 41),
('E42', 'operational', 'Ereignisprotokolle', 'Event Logs', 42),
('E43', 'operational', 'Alarmberichte', 'Alarm Reports', 43),
('E44', 'operational', 'Incident-Report', 'Incident Report', 44),
('E45', 'operational', 'Wartungsbericht', 'Maintenance Report', 45),
-- Extended evidence
('E46', 'extended', 'Redundanzpruefung', 'Redundancy Verification', 46),
('E47', 'extended', 'Sicherheitsvalidierung', 'Safety Validation', 47),
('E48', 'extended', 'Cyber-Security-Audit', 'Cyber Security Audit', 48),
('E49', 'extended', 'Konfigurationspruefung', 'Configuration Review', 49),
('E50', 'extended', 'Endabnahmebericht', 'Final Acceptance Report', 50)
ON CONFLICT (id) DO NOTHING;

View File

@@ -17,84 +17,139 @@ Das IACE-Modul unterstuetzt die vollstaendige CE-Konformitaetsbewertung von Masc
---
## SEPA Risikomodell
## Risikomodell (Dual-Modus)
IACE verwendet das **SEPA-Modell** (Severity × Exposure × Probability × Avoidance):
IACE unterstuetzt zwei Betriebsmodi fuer die Risikobewertung:
### Formel
### Legacy-Modus (S×E×P)
| Avoidance | Formel | Beschreibung |
|-----------|--------|--------------|
| `0` (Standard) | `S × E × P` | Backward-kompatibel, kein Avoidance-Faktor |
| `15` | `S × E × P × (A / 3.0)` | Avoidance-faktor aktiv (3 = neutral) |
| `0` (Standard) | `R = S × E × P` | Backward-kompatibel, kein Avoidance-Faktor |
### Avoidance-Skala
| Wert | Bedeutung |
|------|-----------|
| 1 | Leicht vermeidbar (klare Warnung, langsame Bewegung) |
| 2 | Eher vermeidbar |
| 3 | Neutral (kein Einfluss) |
| 4 | Schwer vermeidbar |
| 5 | Nicht vermeidbar (sofortige Auswirkung) |
### Schwellwerte (Residualrisiko)
**Schwellwerte (Legacy):**
| Schwelle | Level |
|----------|-------|
| 75 | critical |
| 40 | high |
| 15 | medium |
| 5 | low |
| >= 75 | critical |
| >= 40 | high |
| >= 15 | medium |
| >= 5 | low |
| < 5 | negligible |
### ISO-Modus (S×F×P×A) — ab v2.0
Wenn `avoidance >= 1`, wird automatisch der ISO-Modus aktiviert:
| Formel | Beschreibung |
|--------|--------------|
| `R = S × F × P × A` | Direkte 4-Faktor-Multiplikation (KEIN /3.0) |
**Faktoren:**
| Faktor | Skala | Beschreibung |
|--------|-------|--------------|
| **S** (Severity) | 15 | Schwere des moeglichen Schadens |
| **F** (Frequency/Exposure) | 15 | Haeufigkeit/Dauer der Exposition |
| **P** (Probability) | 15 | Wahrscheinlichkeit des Eintretens |
| **A** (Avoidance) | 15 | Moeglichkeit der Vermeidung (1=leicht, 5=nicht vermeidbar) |
**Schwellwerte (ISO-Modus):**
| Schwelle | Level | Farbe |
|----------|-------|-------|
| > 300 | not_acceptable | Dunkelrot |
| 151300 | very_high | Dunkelorange |
| 61150 | high | Rot |
| 2160 | medium | Gelb |
| 120 | low | Gruen |
### ALARP-Akzeptanz
- `residualRisk < 15` → akzeptabel
- `residualRisk < 40` + alle Minderungsschritte verifiziert + Begruendung → akzeptabel (ALARP)
- `residualRisk 40` → nicht akzeptabel (blockiert CE-Export)
- `residualRisk >= 40` → nicht akzeptabel (blockiert CE-Export)
### Schutzmassnahmen-Hierarchie (3-Stufen)
Die Risikobehandlung folgt einer verbindlichen Hierarchie:
| Stufe | Typ | Beschreibung |
|-------|-----|--------------|
| 1 | **Design** | Inhaerent sichere Konstruktion (z.B. Begrenzung von Kraeften, Geschwindigkeiten) |
| 2 | **Schutzeinrichtung** | Technische Schutzmassnahmen (z.B. Schutzgitter, Lichtvorhang, STO) |
| 3 | **Information** | Hinweise, Warnungen, Schulung (z.B. Sicherheitskennzeichnung, Betriebsanleitung) |
!!! warning "Hierarchie-Regel"
Informationsmassnahmen (Stufe 3) duerfen **nicht** als alleinige Primaermassnahme akzeptiert werden, wenn Design- oder Schutzmassnahmen technisch moeglich sind. Das System prueft dies automatisch und gibt eine Warnung aus.
---
## Hazard-Library
Die eingebaute Hazard-Library enthaelt **~140 Eintraege** in 24 Kategorien:
Die eingebaute Hazard-Library enthaelt **150+ Eintraege** in 28 Kategorien. Alle Eintraege verwenden eigene Formulierungen und referenzieren Normen nur als Methodenquelle.
### Urspruengliche Kategorien (12)
### KI/Cyber-Kategorien (12)
| Kategorie | Eintraege | Beschreibung |
|-----------|-----------|--------------|
| `false_classification` | 4 | Falsche KI-Klassifikation |
| `timing_error` | 3 | Echtzeit-Verletzungen |
| `data_poisoning` | 2 | Manipulierte Trainingsdaten |
| `model_drift` | 3 | Modell-Verschlechterung |
| `sensor_spoofing` | 3 | Sensor-Manipulation |
| `communication_failure` | 3 | Kommunikationsausfall |
| `unauthorized_access` | 4 | Unberechtigter Zugriff |
| `firmware_corruption` | 3 | Firmware-Beschaedigung |
| `safety_boundary_violation` | 4 | Sicherheitsgrenzwert-Verletzung |
| `mode_confusion` | 3 | Betriebsart-Verwechslung |
| `unintended_bias` | 2 | Unbeabsichtigte Diskriminierung |
| `update_failure` | 3 | Update-Fehler |
| Kategorie | Beschreibung |
|-----------|--------------|
| `false_classification` | Falsche KI-Klassifikation |
| `timing_error` | Echtzeit-Verletzungen |
| `data_poisoning` | Manipulierte Trainingsdaten |
| `model_drift` | Modell-Verschlechterung |
| `sensor_spoofing` | Sensor-Manipulation |
| `communication_failure` | Kommunikationsausfall |
| `unauthorized_access` | Unberechtigter Zugriff |
| `firmware_corruption` | Firmware-Beschaedigung |
| `safety_boundary_violation` | Sicherheitsgrenzwert-Verletzung |
| `mode_confusion` | Betriebsart-Verwechslung |
| `unintended_bias` | Unbeabsichtigte Diskriminierung |
| `update_failure` | Update-Fehler |
### Neue Kategorien (12, v2.0)
### Software/Hardware-Kategorien (12)
| Kategorie | Eintraege | Beschreibung |
|-----------|-----------|--------------|
| `software_fault` | 10 | Race Condition, Stack Overflow, Integer Overflow, Deadlock... |
| `hmi_error` | 8 | Falsche Einheit, fehlender Alarm, Quittierung ohne Ursache... |
| `mechanical_hazard` | 6 | Unerwarteter Anlauf, Restenergie, Teileauswurf... |
| `electrical_hazard` | 6 | Elektrischer Schlag, Lichtbogen, gespeicherte Energie... |
| `thermal_hazard` | 4 | Ueberhitzung, Brandgefahr, Einfrieren... |
| `emc_hazard` | 5 | EMV-Stoerabstrahlung, ESD, HF-Stoerung... |
| `configuration_error` | 8 | Falscher Safety-Param, Hard-coded Credentials, Debug-Mode... |
| `safety_function_failure` | 8 | Not-Halt, STO, Schutztuer, Zweihand-Taster... |
| `logging_audit_failure` | 5 | Fehlende Protokollierung, Log-Manipulation, Overflow... |
| `integration_error` | 8 | Datentyp-Mismatch, Endianness, Buffer Overflow, Heartbeat... |
| `environmental_hazard` | 5 | Temperatur, Feuchtigkeit, Vibration, Kontamination... |
| `maintenance_hazard` | 6 | LOTO fehlt, Wartung bei laufender Maschine, Wiederanlauf... |
| Kategorie | Beschreibung |
|-----------|--------------|
| `software_fault` | Race Condition, Stack Overflow, Integer Overflow, Deadlock |
| `hmi_error` | Falsche Einheit, fehlender Alarm, Quittierung ohne Ursache |
| `mechanical_hazard` | Quetschen, Scheren, Einziehen, Herabfallende Teile, Instabilitaet |
| `electrical_hazard` | Elektrischer Schlag, Lichtbogen, Ueberstrom, Erdungsfehler |
| `thermal_hazard` | Ueberhitzung, Brandgefahr, Einfrieren, Waermestrahlung |
| `emc_hazard` | EMV-Stoerabstrahlung, ESD, HF-Stoerung |
| `configuration_error` | Falscher Safety-Param, Hard-coded Credentials, Debug-Mode |
| `safety_function_failure` | Not-Halt, STO, Schutztuer, Zweihand-Taster |
| `logging_audit_failure` | Fehlende Protokollierung, Log-Manipulation, Overflow |
| `integration_error` | Datentyp-Mismatch, Endianness, Buffer Overflow, Heartbeat |
| `environmental_hazard` | Temperatur, Feuchtigkeit, Vibration, Kontamination |
| `maintenance_hazard` | LOTO fehlt, Wartung bei laufender Maschine, Wiederanlauf |
**Filter:** `GET /sdk/v1/iace/hazard-library?category=software_fault&componentType=sw`
### Physikalische Kategorien (4, ab v2.0)
| Kategorie | Beschreibung |
|-----------|--------------|
| `pneumatic_hydraulic` | Druckverlust, Druckfreisetzung, Schlauchpeitschen, unerwartete Bewegung |
| `noise_vibration` | Gehoerschaedigung, Hand-Arm-Vibration, Ganzkoerpervibration |
| `ergonomic` | Fehlbedienung, Zwangshaltung, Ueberforderung, Repetitive Belastung |
| `material_environmental` | Staub, Rauch, Daempfe, chemische Exposition, Leckagen |
### Erweiterte Felder (ab v2.0)
Jeder Hazard-Library-Eintrag enthaelt zusaetzlich:
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `default_exposure` | int (15) | Standard-Expositionswert |
| `default_avoidance` | int (15) | Standard-Vermeidbarkeit |
| `typical_causes` | string[] | Typische Ursachen |
| `typical_harm` | string | Typische Schadensfolge |
| `relevant_lifecycle_phases` | string[] | Relevante Lebensphasen |
| `recommended_measures_design` | string[] | Empfohlene Design-Massnahmen |
| `recommended_measures_technical` | string[] | Empfohlene technische Massnahmen |
| `recommended_measures_information` | string[] | Empfohlene Informationsmassnahmen |
| `suggested_evidence` | string[] | Vorgeschlagene Nachweisdokumente |
| `related_keywords` | string[] | Suchbegriffe |
**Filter:** `GET /sdk/v1/iace/hazard-library?category=mechanical_hazard&componentType=mechanical`
---
@@ -117,14 +172,134 @@ Die Controls-Library enthaelt **200 Eintraege** in 6 Domaenen:
---
## Schutzmassnahmen-Bibliothek (ab v2.0)
Zusaetzlich zur Controls-Library bietet IACE eine **Schutzmassnahmen-Bibliothek** mit **160 Eintraegen**, kategorisiert nach der 3-Stufen-Hierarchie:
| ReductionType | Eintraege | Beispiele |
|---------------|-----------|-----------|
| `design` | ~55 | Kraftbegrenzung, Formschluessige Sicherung, Redundante Sensorik |
| `protective` | ~60 | Schutzgitter, Lichtvorhang, STO, Druckbegrenzungsventil |
| `information` | ~45 | Sicherheitskennzeichnung, Betriebsanleitung, Schulungsprogramm |
**Filter:** `GET /sdk/v1/iace/protective-measures-library?category=mechanical_hazard`
---
## Lebensphasen (25)
Die Risikobeurteilung beruecksichtigt **25 Lebensphasen** einer Maschine:
| Phase | DE | EN |
|-------|----|----|
| `transport` | Transport | Transport |
| `storage` | Lagerung | Storage |
| `assembly` | Montage | Assembly |
| `installation` | Aufstellung | Installation |
| `commissioning` | Inbetriebnahme | Commissioning |
| `parameterization` | Parametrierung | Parameterization |
| `setup` | Einrichten | Setup |
| `normal_operation` | Normalbetrieb | Normal Operation |
| `auto_operation` | Automatikbetrieb | Automatic Operation |
| `manual_operation` | Handbetrieb | Manual Operation |
| `teach_mode` | Teach-Modus | Teach Mode |
| `production_start` | Produktionsstart | Production Start |
| `production_stop` | Produktionsstopp | Production Stop |
| `process_monitoring` | Prozessueberwachung | Process Monitoring |
| `cleaning` | Reinigung | Cleaning |
| `inspection` | Inspektion | Inspection |
| `maintenance` | Wartung | Maintenance |
| `calibration` | Kalibrierung | Calibration |
| `repair` | Reparatur | Repair |
| `software_update` | Software-Update | Software Update |
| `remote_maintenance` | Fernwartung | Remote Maintenance |
| `fault_clearing` | Stoerungsbeseitigung | Fault Clearing |
| `changeover` | Umruestung | Changeover |
| `decommissioning` | Ausserbetriebnahme | Decommissioning |
| `disposal` | Demontage/Entsorgung | Dismantling/Disposal |
**API:** `GET /sdk/v1/iace/lifecycle-phases`
---
## Betroffene Personen (20 Rollen)
Jede Gefaehrdung kann einer oder mehreren betroffenen Personengruppen zugeordnet werden:
| Rolle | DE | EN |
|-------|----|----|
| `operator` | Bediener | Operator |
| `setup_personnel` | Einrichter | Setup Personnel |
| `maintenance_tech` | Wartungstechniker | Maintenance Technician |
| `cleaning_staff` | Reinigungspersonal | Cleaning Staff |
| `supervisor` | Aufsichtsperson | Supervisor |
| `programmer` | Programmierer/Integrator | Programmer/Integrator |
| `trainee` | Auszubildender | Trainee |
| `temp_worker` | Leiharbeiter | Temporary Worker |
| `visitor` | Besucher | Visitor |
| `third_party` | Dritte/Passanten | Third Party/Bystander |
| `transport_personnel` | Transportpersonal | Transport Personnel |
| `commissioning_eng` | Inbetriebnahme-Ingenieur | Commissioning Engineer |
| `quality_inspector` | Qualitaetspruefer | Quality Inspector |
| `safety_officer` | Sicherheitsbeauftragter | Safety Officer |
| `electrical_tech` | Elektrofachkraft | Electrical Technician |
| `it_admin` | IT-Administrator | IT Administrator |
| `remote_operator` | Fernbediener | Remote Operator |
| `emergency_responder` | Ersthelfer/Rettungskraft | Emergency Responder |
| `contractor` | Fremdfirma-Mitarbeiter | Contractor |
| `disabled_person` | Person mit Einschraenkung | Person with Disability |
**API:** `GET /sdk/v1/iace/roles`
---
## Nachweistypen (50 in 7 Kategorien)
Fuer die Verifikation stehen **50 Nachweistypen** zur Auswahl:
| Kategorie | Beispiele |
|-----------|-----------|
| **Konstruktion** | Risikobeurteilung, Sicherheitskonzept, Schaltplan, Pneumatikplan |
| **Berechnung** | Festigkeitsberechnung, Thermische Simulation, FMEA |
| **Pruefung** | Funktionspruefung, Druckpruefung, EMV-Messung, Isolationspruefung |
| **Zertifizierung** | Baumuster-Pruefbescheinigung, SIL/PL-Zertifikat, CE-Konformitaetserklaerung |
| **Software** | Code-Review-Protokoll, Statische Analyse, Unit-Test-Report, Penetrationstest |
| **Betrieb** | Betriebsanleitung, Wartungsplan, Schulungsnachweis, Notfallplan |
| **Ueberwachung** | Inspektionsbericht, Kalibrierprotokoll, Audit-Report, Maengelprotokoll |
**API:** `GET /sdk/v1/iace/evidence-types?category=pruefung`
---
## Verifikationsmethoden (10)
| Methode | Beschreibung |
|---------|--------------|
| `design_review` | Systematische Pruefung von Konstruktionsunterlagen |
| `calculation` | Rechnerischer Nachweis (Festigkeit, Thermik, SIL) |
| `test_report` | Pruefbericht aus Labor- oder Feldversuchen |
| `validation` | Nachweis der Gebrauchstauglichkeit unter realen Bedingungen |
| `electrical_test` | Isolationsmessung, Schutzleiter, Spannungspruefung |
| `software_test` | Unit-Test, Integrationstest, statische Analyse |
| `penetration_test` | Sicherheitstest der IT/OT-Infrastruktur |
| `acceptance_protocol` | Formales Abnahmeprotokoll mit Checkliste |
| `user_test` | Anwendertest unter realistischen Einsatzbedingungen |
| `documentation_release` | Formale Freigabe von Dokumenten und Anleitungen |
---
## API-Endpunkte (30+)
### Libraries (projektunabhaengig)
### Libraries & Referenzdaten (projektunabhaengig)
| Methode | Pfad | Beschreibung |
|---------|------|--------------|
| GET | `/sdk/v1/iace/hazard-library` | Alle Gefaehrdungen (~140) |
| GET | `/sdk/v1/iace/hazard-library` | Alle Gefaehrdungen (150+) |
| GET | `/sdk/v1/iace/controls-library` | Alle Controls (200) |
| GET | `/sdk/v1/iace/protective-measures-library` | Schutzmassnahmen-Bibliothek (160) |
| GET | `/sdk/v1/iace/lifecycle-phases` | 25 Lebensphasen (DE/EN) |
| GET | `/sdk/v1/iace/roles` | 20 betroffene Personengruppen (DE/EN) |
| GET | `/sdk/v1/iace/evidence-types` | 50 Nachweistypen in 7 Kategorien |
### Projektmanagement
@@ -170,7 +345,8 @@ Die Controls-Library enthaelt **200 Eintraege** in 6 Domaenen:
| POST | `/sdk/v1/iace/projects/:id/hazards/suggest` | KI-gestuetzte Vorschlaege |
| POST | `/sdk/v1/iace/projects/:id/hazards/:hid/assess` | Risikobewertung (SEPA) |
| POST | `/sdk/v1/iace/projects/:id/hazards/:hid/reassess` | Neubewertung nach Minderung |
| GET | `/sdk/v1/iace/projects/:id/risk-summary` | Aggregierte Risikoübersicht |
| GET | `/sdk/v1/iace/projects/:id/risk-summary` | Aggregierte Risikouebersicht |
| POST | `/sdk/v1/iace/projects/:id/validate-mitigation-hierarchy` | Hierarchie-Pruefung (3-Stufen) |
### Minderung & Verifikation
@@ -290,19 +466,30 @@ curl -sk https://macmini:8093/sdk/v1/iace/controls-library | python3 -c "import
---
## Beispiel: Risikobewertung mit Avoidance
## Beispiel: Risikobewertung
### Legacy-Modus (A=0)
```bash
curl -sk -X POST https://macmini:8093/sdk/v1/iace/projects/{id}/hazards/{hid}/assess \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: <tenant-uuid>" \
-d '{"severity": 5, "exposure": 3, "probability": 3, "avoidance": 0}'
```
Ergebnis: `R = 5 × 3 × 3 = 45`**high**
### ISO-Modus (A >= 1)
```bash
# Risikobewertung mit Avoidance-Faktor (A=5: nicht vermeidbar)
curl -sk -X POST https://macmini:8093/sdk/v1/iace/projects/{id}/hazards/{hid}/assess \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: <tenant-uuid>" \
-d '{
"hazard_id": "<hid>",
"severity": 5,
"exposure": 3,
"probability": 3,
"avoidance": 5,
"avoidance": 4,
"control_maturity": 2,
"control_coverage": 0.6,
"test_evidence_strength": 0.5,
@@ -310,9 +497,7 @@ curl -sk -X POST https://macmini:8093/sdk/v1/iace/projects/{id}/hazards/{hid}/as
}'
```
Ohne Avoidance (A=0): `InherentRisk = 5×3×3 = 45`
Mit Avoidance A=5: `InherentRisk = 5×3×3×(5/3) = 75` (kritisch!)
Mit Avoidance A=1: `InherentRisk = 5×3×3×(1/3) = 15` (medium)
Ergebnis: `R = 5 × 3 × 3 × 4 = 180`**very_high** (ISO-Schwellwerte)
---
@@ -338,11 +523,35 @@ curl -sk "https://macmini:8093/sdk/v1/iace/controls-library?category=software_fa
| `iace_components` | System-Komponenten |
| `iace_regulatory_classifications` | Regulierungsklassifizierungen |
| `iace_hazard_library` | Benutzerdefinierte Hazard-Templates |
| `iace_hazards` | Projektspezifische Gefaehrdungen |
| `iace_risk_assessments` | SEPA-Risikobewertungen (inkl. avoidance) |
| `iace_hazards` | Projektspezifische Gefaehrdungen (inkl. lifecycle_phase, affected_person, trigger_event) |
| `iace_risk_assessments` | Risikobewertungen (Legacy S×E×P + ISO S×F×P×A) |
| `iace_mitigations` | Minderungsmassnahmen |
| `iace_verification_plans` | Verifikationsplaene |
| `iace_evidence` | Nachweise (Uploads) |
| `iace_tech_file_sections` | CE-Akte-Abschnitte |
| `iace_monitoring_events` | Post-Market-Ereignisse |
| `iace_audit_trail` | Unveraenderbares Audit-Log |
| `iace_lifecycle_phases` | 25 Lebensphasen (DE/EN) |
| `iace_roles` | 20 betroffene Personengruppen (DE/EN) |
| `iace_evidence_types` | 50 Nachweistypen in 7 Kategorien |
---
## Rechtlicher Hinweis — Normenreferenz
!!! warning "Urheberrecht bei Normen"
Saemtliche Inhalte des IACE-Moduls (Gefaehrdungsbibliothek, Schutzmassnahmen-Katalog,
Risikomodell, Lebensphasen, Rollen) sind **eigenstaendig formuliert**. Normen wie
ISO 12100, DIN EN 62443, IEC 61508 etc. werden ausschliesslich als **Methodenreferenz**
in den Metadaten gefuehrt (z.B. `"methodology_reference": "ISO 12100"`).
Es wird **kein normativer Text** reproduziert — keine Tabellen, Risikoklassifikationen,
Prozesstexte oder Checklisten aus Normen. Dies ist konform mit §51 UrhG (Zitatrecht).
Fuer die Anwendung der vollstaendigen Normen muss die jeweilige Norm separat
ueber DIN Media (beuth.de) oder ISO erworben werden.
**Beispiel fuer konforme Normenreferenz in generierten Dokumenten:**
> Die Risikobeurteilung wurde unter Beruecksichtigung allgemein anerkannter Methoden
> der Maschinensicherheit durchgefuehrt (u.a. angelehnt an ISO 12100).