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
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>
83 lines
2.8 KiB
Python
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:
|
|
...
|