Files
deklarix/internal/rules/rule.go
noroot 15bf277bee feat: add jurisdiction field to rules, facts and extraction
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>
2026-08-27 13:47:08 +02:00

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
}