feat(iace): cite ESAW source + license on risk-frequency anchors

Surfaces the public-statistics provenance for the contact-mode probability
tiers so generated risk numbers are auditable and attributed (not RAG —
~a dozen stable aggregate facts are better as a license-tagged code table).

- risk_data_sources.go: RiskEvidence register (Eurostat ESAW figures + CC BY
  4.0 attribution) for the documented contact modes; RiskDataSourcesNote.
- risk_suggestion.go: the W justification now cites the actual ESAW share +
  license where documented; RiskSuggestion gains a data_source field.
- GET /iace/risk-data-sources returns the evidence register + attribution.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-11 09:14:36 +02:00
parent 289988d23e
commit ee64b7e95c
4 changed files with 93 additions and 2 deletions
@@ -46,6 +46,7 @@ type RiskSuggestion struct {
ContactMode string `json:"contact_mode"`
EN62061 EN62061Suggestion `json:"en62061"`
FineKinney FineKinneySuggestion `json:"fine_kinney"`
DataSource *RiskEvidence `json:"data_source,omitempty"`
Note string `json:"note"`
}
@@ -65,6 +66,14 @@ func BuildRiskSuggestion(hz *Hazard) RiskSuggestion {
modeLabel = "unbestimmt"
}
// Cite the actual public statistic + license for the W anchor where documented.
wJustification := fmt.Sprintf("Wahrscheinlichkeit W aus ESAW-Haeufigkeit der Kontaktart '%s'", modeLabel)
var dataSource *RiskEvidence
if ev, ok := RiskEvidenceFor(mode); ok {
wJustification += fmt.Sprintf(" (%s: %s; %s)", ev.Label, ev.Stat, ev.Attribution)
dataSource = &ev
}
// EN-62061-style (F/W/P/S)
s := EstimateSeverity(cats, scenario, 0)
f := EstimateFrequency(lifecycle)
@@ -81,7 +90,7 @@ func BuildRiskSuggestion(hz *Hazard) RiskSuggestion {
EN62061: EN62061Suggestion{
Severity: SuggestedValue{float64(s), fmt.Sprintf("Schwere S%d aus Verletzungsbild der Kontaktart '%s' (NIOSH/OSHA/MIL-STD-882)", s, modeLabel)},
Frequency: SuggestedValue{float64(f), "Haeufigkeit F aus Lebensphasen-Exposition des Projekts"},
Probability: SuggestedValue{float64(w), fmt.Sprintf("Wahrscheinlichkeit W aus ESAW-Haeufigkeit der Kontaktart '%s'", modeLabel)},
Probability: SuggestedValue{float64(w), wJustification},
Avoidance: SuggestedValue{float64(p), fmt.Sprintf("Vermeidbarkeit P aus Kinematik der Kontaktart '%s'", modeLabel)},
Score: idx,
Level: level,
@@ -96,7 +105,8 @@ func BuildRiskSuggestion(hz *Hazard) RiskSuggestion {
Action: fk.Action,
Formula: "R = P × E × C",
},
Note: "Begruendete Vorschlagswerte (BreakPilot, oeffentliche Datenquellen). Vom Sachverstaendigen anpassbar.",
DataSource: dataSource,
Note: "Begruendete Vorschlagswerte (BreakPilot, oeffentliche Datenquellen). Vom Sachverstaendigen anpassbar.",
}
}