Files
breakpilot-compliance/backend-compliance/compliance/services/checkers/base.py
T
Benjamin_Boenisch 38a347a82a
CI / detect-changes (push) Successful in 7s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Successful in 9s
CI / validate-canonical-controls (push) Successful in 12s
CI / loc-budget (push) Successful in 24s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 3m11s
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 24s
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
feat(platform): live-wire AGB v2 + DSE v3 + Architektur-Tab (#29)
AGB v2 (decision_method routing, 71%FP->~0) + DSE v3 (4-layer, recovered from container) + Architektur-Tab into /sdk/agent live path. Incl CI robustness (detect-changes.sh + PR-head checkout) + security (hardcoded Qdrant key removed, gitleaks allowlist).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-21 12:58:26 +00:00

83 lines
2.8 KiB
Python

"""Pruefer-Library — gemeinsames Interface. Siehe docs platform_checker_matrix.md.
Ein Checker prueft EINEN Control gegen EIN Dokument und liefert: vorhanden / fehlt
/ unklar (+ Evidence). Module (DSE/Impressum/AGB/...) liefern nur Control-Metadaten
ueber `ControlSpec` (verification_method + decision_method + checker-spezifische
Config); die Engine routet method-agnostisch zum passenden Checker.
Ziel der Plattform: 14k Controls -> 7 Pruefertypen -> wenige Pruefer. Ein neues
Modul wird damit ein Klassifizierungs-, kein Forschungsproblem.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Optional, Protocol, runtime_checkable
class VerificationMethod:
"""Achse 1 — WELCHER Pruefer-Typ (Kategorie)."""
FIELD = "FIELD"
REFERENCE = "REFERENCE"
BEHAVIOR = "BEHAVIOR"
PRESENTATION = "PRESENTATION"
CONTENT = "CONTENT"
PROCESS = "PROCESS"
TECHNICAL = "TECHNICAL"
CONTRACTUAL = "CONTRACTUAL"
class DecisionMethod:
"""Achse 2 — WIE entschieden wird (konkreter Mechanismus)."""
REGEX = "REGEX"
EMBEDDING = "EMBEDDING"
LLM = "LLM"
LINK_RESOLVER = "LINK_RESOLVER"
PLAYWRIGHT = "PLAYWRIGHT"
AUDIT = "AUDIT"
SCANNER = "SCANNER"
@dataclass
class ControlSpec:
"""Routing-Metadaten + checker-spezifische Config eines Controls. Module fuellen
nur die fuer ihren decision_method relevanten Felder."""
control_id: str
verification_method: str
decision_method: str
label: str = ""
severity: str = "MEDIUM"
patterns: list[str] = field(default_factory=list) # FIELD/REGEX, REFERENCE
paraphrases: list[str] = field(default_factory=list) # CONTENT (EMBEDDING/LLM)
embed_threshold: Optional[float] = None # EMBEDDING (per-Control)
topic_regex: str = "" # LLM: Section-Retrieval
question: str = "" # LLM: Pruef-Frage
extra: dict[str, Any] = field(default_factory=dict)
@dataclass
class DocContext:
"""Das zu pruefende Artefakt. `text` = Volltext; `url`/`rendered` fuer
PRESENTATION/BEHAVIOR (Playwright) — spaeter."""
text: str = ""
url: str = ""
rendered: Any = None
@dataclass
class CheckResult:
present: Optional[bool] # True=erfuellt, False=fehlt, None=unklar (fail-safe)
evidence: str = ""
confidence: float = 0.0
source: str = "" # welcher Pruefer/Tier geantwortet hat
detail: dict[str, Any] = field(default_factory=dict)
@runtime_checkable
class Checker(Protocol):
"""Alle Pruefer haben dieselbe Signatur -> die Engine ist method-agnostisch und
routet nur ueber ctrl.verification_method / ctrl.decision_method."""
verification_method: str
async def check(self, ctrl: ControlSpec, doc: DocContext) -> CheckResult:
...