Rule now carries a required Jurisdiction (land) field, and Facts a matching Jurisdiction supplied by the caller (like Platform — no legal jurisdiction can be read off a caption or image, so the model never guesses it). Evaluate() only lets a rule fire when its jurisdiction matches the facts' jurisdiction. This is the structural half of "deutsche Rechtslage zuerst, Struktur für Österreich und Schweiz vorgesehen": a future AT/CH rule set can be added as plain new YAML files without touching existing DE rules, but no AT/CH content is added now — that needs its own legal research first, same as WK-001/WK-004 needed for Germany. WK-001 and WK-004 are tagged land: DE, all golden fixtures carry jurisdiction: DE, and extract.Input passes Jurisdiction through unchanged into the returned Facts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
63 lines
2.0 KiB
Go
63 lines
2.0 KiB
Go
package rules
|
|
|
|
// Severity ist die Schwere eines Findings.
|
|
type Severity string
|
|
|
|
const (
|
|
SeverityLow Severity = "niedrig"
|
|
SeverityMedium Severity = "mittel"
|
|
SeverityHigh Severity = "hoch"
|
|
)
|
|
|
|
// Rule ist eine versionierte Regel aus einer YAML-Datei in rules/.
|
|
// Regel-IDs werden nie umbenannt oder wiederverwendet — Änderungen an
|
|
// einer Regel erhöhen die Version.
|
|
//
|
|
// Jurisdiction ordnet eine Regel genau einer Rechtsordnung zu (aktuell
|
|
// nur "DE" — deutsche Rechtslage zuerst). Damit lassen sich künftige
|
|
// AT/CH-Regeln als zusätzliche Dateien ergänzen, ohne bestehende Regeln
|
|
// anzufassen: eine Regel gilt nie für mehrere Rechtsordnungen gleichzeitig,
|
|
// auch wenn sich Gesetzestexte ähneln — jede Rechtsordnung bekommt ihre
|
|
// eigene, einzeln geprüfte Fundstelle.
|
|
type Rule struct {
|
|
ID string `yaml:"id"`
|
|
Version int `yaml:"version"`
|
|
Jurisdiction string `yaml:"land"`
|
|
Title string `yaml:"titel"`
|
|
Condition Condition `yaml:"bedingung"`
|
|
Severity Severity `yaml:"schwere"`
|
|
Sources []string `yaml:"fundstelle"`
|
|
Fix string `yaml:"korrektur"`
|
|
}
|
|
|
|
// Condition ist eine flache UND-Bedingung über Facts. Ein nil/leeres
|
|
// Feld bedeutet "keine Einschränkung durch dieses Feld".
|
|
type Condition struct {
|
|
Consideration []Consideration `yaml:"gegenleistung,omitempty"`
|
|
DisclosurePresent *bool `yaml:"kennzeichnung_vorhanden,omitempty"`
|
|
DisclosureBeforeCut *bool `yaml:"kennzeichnung_vor_kuerzung,omitempty"`
|
|
}
|
|
|
|
// Matches prüft, ob f alle gesetzten Bedingungsfelder erfüllt.
|
|
func (c Condition) Matches(f Facts) bool {
|
|
if len(c.Consideration) > 0 {
|
|
found := false
|
|
for _, allowed := range c.Consideration {
|
|
if allowed == f.Consideration {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
return false
|
|
}
|
|
}
|
|
if c.DisclosurePresent != nil && *c.DisclosurePresent != f.DisclosurePresent {
|
|
return false
|
|
}
|
|
if c.DisclosureBeforeCut != nil && *c.DisclosureBeforeCut != f.DisclosureBeforeCut {
|
|
return false
|
|
}
|
|
return true
|
|
}
|