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
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:
@@ -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>
|
||||
|
||||
@@ -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 "Information"</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 → Schutz → 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>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -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 }> = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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"}},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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, ®ulationReferences,
|
||||
&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, ®ulationReferences,
|
||||
&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
|
||||
}
|
||||
|
||||
58
ai-compliance-sdk/migrations/018_iace_iso12100.sql
Normal file
58
ai-compliance-sdk/migrations/018_iace_iso12100.sql
Normal 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;
|
||||
149
ai-compliance-sdk/migrations/019_iace_extended_libraries.sql
Normal file
149
ai-compliance-sdk/migrations/019_iace_extended_libraries.sql
Normal 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;
|
||||
@@ -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 |
|
||||
| `1–5` | `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) | 1–5 | Schwere des moeglichen Schadens |
|
||||
| **F** (Frequency/Exposure) | 1–5 | Haeufigkeit/Dauer der Exposition |
|
||||
| **P** (Probability) | 1–5 | Wahrscheinlichkeit des Eintretens |
|
||||
| **A** (Avoidance) | 1–5 | Moeglichkeit der Vermeidung (1=leicht, 5=nicht vermeidbar) |
|
||||
|
||||
**Schwellwerte (ISO-Modus):**
|
||||
|
||||
| Schwelle | Level | Farbe |
|
||||
|----------|-------|-------|
|
||||
| > 300 | not_acceptable | Dunkelrot |
|
||||
| 151–300 | very_high | Dunkelorange |
|
||||
| 61–150 | high | Rot |
|
||||
| 21–60 | medium | Gelb |
|
||||
| 1–20 | 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 (1–5) | Standard-Expositionswert |
|
||||
| `default_avoidance` | int (1–5) | 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).
|
||||
|
||||
Reference in New Issue
Block a user