feat: Pass 0b quality — negative actions, container detection, session object classes
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 33s
CI/CD / test-python-backend-compliance (push) Successful in 30s
CI/CD / test-python-document-crawler (push) Successful in 21s
CI/CD / test-python-dsms-gateway (push) Successful in 16s
CI/CD / validate-canonical-controls (push) Successful in 10s
CI/CD / Deploy (push) Successful in 2s

4 error class fixes from AUTH-1052 quality review:
1. Prohibitive action types (prevent/exclude/forbid) for "dürfen keine", "verboten" etc.
2. Container object detection (Sitzungsverwaltung, Token-Schutz → _requires_decomposition)
3. Session-specific object classes (session, cookie, jwt, federated_assertion)
4. Session lifecycle actions (invalidate, issue, rotate, enforce) with templates + severity caps

76 new tests (303 total), all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-28 17:24:19 +01:00
parent 447ec08509
commit 712fa8cb74
2 changed files with 547 additions and 7 deletions

View File

@@ -459,7 +459,9 @@ def _split_compound_action(action: str) -> list[str]:
# ── 2. Action Type Classification (18 types) ────────────────────────────
_ACTION_PRIORITY = [
"prevent", "exclude", "forbid",
"implement", "configure", "encrypt", "restrict_access",
"enforce", "invalidate", "issue", "rotate",
"monitor", "review", "assess", "audit",
"test", "verify", "validate",
"report", "notify", "train",
@@ -470,7 +472,41 @@ _ACTION_PRIORITY = [
]
_ACTION_KEYWORDS: list[tuple[str, str]] = [
# Multi-word patterns first (longest match wins)
# ── Negative / prohibitive actions (highest priority) ────
("dürfen keine", "prevent"),
("dürfen nicht", "prevent"),
("darf keine", "prevent"),
("darf nicht", "prevent"),
("nicht zulässig", "forbid"),
("nicht erlaubt", "forbid"),
("nicht gestattet", "forbid"),
("untersagt", "forbid"),
("verboten", "forbid"),
("nicht enthalten", "exclude"),
("nicht übertragen", "prevent"),
("nicht übermittelt", "prevent"),
("nicht wiederverwendet", "prevent"),
("nicht gespeichert", "prevent"),
("verhindern", "prevent"),
("unterbinden", "prevent"),
("ausschließen", "exclude"),
("vermeiden", "prevent"),
("ablehnen", "exclude"),
("zurückweisen", "exclude"),
# ── Session / lifecycle actions ──────────────────────────
("ungültig machen", "invalidate"),
("invalidieren", "invalidate"),
("widerrufen", "invalidate"),
("session beenden", "invalidate"),
("vergeben", "issue"),
("ausstellen", "issue"),
("erzeugen", "issue"),
("generieren", "issue"),
("rotieren", "rotate"),
("erneuern", "rotate"),
("durchsetzen", "enforce"),
("erzwingen", "enforce"),
# ── Multi-word patterns (longest match wins) ─────────────
("aktuell halten", "maintain"),
("aufrechterhalten", "maintain"),
("sicherstellen", "ensure"),
@@ -565,6 +601,15 @@ _ACTION_KEYWORDS: list[tuple[str, str]] = [
("remediate", "remediate"),
("perform", "perform"),
("obtain", "obtain"),
("prevent", "prevent"),
("forbid", "forbid"),
("exclude", "exclude"),
("invalidate", "invalidate"),
("revoke", "invalidate"),
("issue", "issue"),
("generate", "issue"),
("rotate", "rotate"),
("enforce", "enforce"),
]
@@ -627,11 +672,29 @@ _OBJECT_CLASS_KEYWORDS: dict[str, list[str]] = {
"access_control": [
"authentifizierung", "autorisierung", "zugriff",
"berechtigung", "passwort", "kennwort", "anmeldung",
"sso", "rbac", "session",
"sso", "rbac",
],
"session": [
"session", "sitzung", "sitzungsverwaltung", "session management",
"session-id", "session-token", "idle timeout",
"inaktivitäts-timeout", "inaktivitätszeitraum",
"logout", "abmeldung",
],
"cookie": [
"cookie", "session-cookie", "secure-flag", "httponly",
"samesite", "cookie-attribut",
],
"jwt": [
"jwt", "json web token", "bearer token",
"jwt-algorithmus", "jwt-signatur",
],
"federated_assertion": [
"assertion", "saml", "oidc", "openid",
"föderiert", "federated", "identity provider",
],
"cryptographic_control": [
"schlüssel", "zertifikat", "signatur", "kryptographi",
"cipher", "hash", "token",
"cipher", "hash", "token", "entropie",
],
"configuration": [
"konfiguration", "einstellung", "parameter",
@@ -1030,6 +1093,85 @@ _ACTION_TEMPLATES: dict[str, dict[str, list[str]]] = {
"Gültigkeitsprüfung mit Zeitstempeln",
],
},
# ── Prevent / Exclude / Forbid (negative norms) ────────────
"prevent": {
"test_procedure": [
"Prüfung, dass {object} technisch verhindert wird",
"Stichprobe: Versuch der verbotenen Aktion schlägt fehl",
"Review der Konfiguration und Zugriffskontrollen",
],
"evidence": [
"Konfigurationsnachweis der Präventionsmassnahme",
"Testprotokoll der Negativtests",
],
},
"exclude": {
"test_procedure": [
"Prüfung, dass {object} ausgeschlossen ist",
"Stichprobe: Verbotene Inhalte/Aktionen sind nicht vorhanden",
"Automatisierter Scan oder manuelle Prüfung",
],
"evidence": [
"Scan-Ergebnis oder Prüfprotokoll",
"Konfigurationsnachweis",
],
},
"forbid": {
"test_procedure": [
"Prüfung, dass {object} untersagt und technisch blockiert ist",
"Verifizierung der Richtlinie und technischen Durchsetzung",
"Stichprobe: Versuch der untersagten Aktion wird abgelehnt",
],
"evidence": [
"Richtlinie mit explizitem Verbot",
"Technischer Nachweis der Blockierung",
],
},
# ── Enforce / Invalidate / Issue / Rotate ────────────────
"enforce": {
"test_procedure": [
"Prüfung der technischen Durchsetzung von {object}",
"Stichprobe: Nicht-konforme Konfigurationen werden automatisch korrigiert oder abgelehnt",
"Review der Enforcement-Regeln und Ausnahmen",
],
"evidence": [
"Enforcement-Policy mit technischer Umsetzung",
"Protokoll erzwungener Korrekturen oder Ablehnungen",
],
},
"invalidate": {
"test_procedure": [
"Prüfung, dass {object} korrekt ungültig gemacht wird",
"Stichprobe: Nach Invalidierung kein Zugriff mehr möglich",
"Verifizierung der serverseitigen Bereinigung",
],
"evidence": [
"Protokoll der Invalidierungsaktionen",
"Testnachweis der Zugriffsverweigerung nach Invalidierung",
],
},
"issue": {
"test_procedure": [
"Prüfung des Vergabeprozesses für {object}",
"Verifizierung der kryptographischen Sicherheit und Entropie",
"Stichprobe: Korrekte Vergabe unter definierten Bedingungen",
],
"evidence": [
"Prozessdokumentation der Vergabe",
"Nachweis der Entropie-/Sicherheitseigenschaften",
],
},
"rotate": {
"test_procedure": [
"Prüfung des Rotationsprozesses für {object}",
"Verifizierung der Rotationsfrequenz und automatischen Auslöser",
"Stichprobe: Alte Artefakte nach Rotation ungültig",
],
"evidence": [
"Rotationsrichtlinie mit Frequenz",
"Rotationsprotokoll mit Zeitstempeln",
],
},
# ── Approve / Remediate ───────────────────────────────────
"approve": {
"test_procedure": [
@@ -1483,6 +1625,25 @@ _OBJECT_SYNONYMS: dict[str, str] = {
"dienstleister": "vendor",
"auftragsverarbeiter": "vendor",
"drittanbieter": "vendor",
# Session management synonyms (2026-03-28)
"sitzung": "session",
"sitzungsverwaltung": "session_mgmt",
"session management": "session_mgmt",
"session-id": "session_token",
"sitzungstoken": "session_token",
"session-token": "session_token",
"idle timeout": "session_timeout",
"inaktivitäts-timeout": "session_timeout",
"inaktivitätszeitraum": "session_timeout",
"abmeldung": "logout",
"cookie-attribut": "cookie_security",
"secure-flag": "cookie_security",
"httponly": "cookie_security",
"samesite": "cookie_security",
"json web token": "jwt",
"bearer token": "jwt",
"föderierte assertion": "federated_assertion",
"saml assertion": "federated_assertion",
}
@@ -1596,11 +1757,33 @@ _COMPOSITE_OBJECT_KEYWORDS: list[str] = [
"soc 2", "soc2", "enisa", "kritis",
]
# Container objects that are too broad for atomic controls.
# These produce titles like "Sichere Sitzungsverwaltung umgesetzt" which
# are not auditable — they encompass multiple sub-requirements.
_CONTAINER_OBJECT_KEYWORDS: list[str] = [
"sitzungsverwaltung", "session management", "session-management",
"token-schutz", "tokenschutz",
"authentifizierungsmechanismen", "authentifizierungsmechanismus",
"sicherheitsmaßnahmen", "sicherheitsmassnahmen",
"schutzmaßnahmen", "schutzmassnahmen",
"zugriffskontrollmechanismen",
"sicherheitsarchitektur",
"sicherheitskontrollen",
"datenschutzmaßnahmen", "datenschutzmassnahmen",
"compliance-anforderungen",
"risikomanagementprozess",
]
_COMPOSITE_RE = re.compile(
"|".join(_FRAMEWORK_KEYWORDS + _COMPOSITE_OBJECT_KEYWORDS),
re.IGNORECASE,
)
_CONTAINER_RE = re.compile(
"|".join(_CONTAINER_OBJECT_KEYWORDS),
re.IGNORECASE,
)
def _is_composite_obligation(obligation_text: str, object_: str) -> bool:
"""Detect framework-level / composite obligations that are NOT atomic.
@@ -1612,6 +1795,17 @@ def _is_composite_obligation(obligation_text: str, object_: str) -> bool:
return bool(_COMPOSITE_RE.search(combined))
def _is_container_object(object_: str) -> bool:
"""Detect overly broad container objects that should not be atomic.
Objects like 'Sitzungsverwaltung' or 'Token-Schutz' encompass multiple
sub-requirements and produce non-auditable controls.
"""
if not object_:
return False
return bool(_CONTAINER_RE.search(object_))
# ── 7c. Output Validator (Negativregeln) ─────────────────────────────────
def _validate_atomic_control(
@@ -1825,11 +2019,17 @@ def _compose_deterministic(
atomic._deadline_hours = deadline_hours # type: ignore[attr-defined]
atomic._frequency = frequency # type: ignore[attr-defined]
# ── Composite / Framework detection ───────────────────────
# ── Composite / Framework / Container detection ────────────
is_composite = _is_composite_obligation(obligation_text, object_)
atomic._is_composite = is_composite # type: ignore[attr-defined]
atomic._atomicity = "composite" if is_composite else "atomic" # type: ignore[attr-defined]
atomic._requires_decomposition = is_composite # type: ignore[attr-defined]
is_container = _is_container_object(object_)
atomic._is_composite = is_composite or is_container # type: ignore[attr-defined]
if is_composite:
atomic._atomicity = "composite" # type: ignore[attr-defined]
elif is_container:
atomic._atomicity = "container" # type: ignore[attr-defined]
else:
atomic._atomicity = "atomic" # type: ignore[attr-defined]
atomic._requires_decomposition = is_composite or is_container # type: ignore[attr-defined]
# ── Validate (log issues, never reject) ───────────────────
validation_issues = _validate_atomic_control(atomic, action_type, object_class)
@@ -3646,6 +3846,12 @@ _ACTION_SEVERITY_CAP: dict[str, str] = {
"configure": "high",
"monitor": "high",
"enforce": "high",
"prevent": "high",
"exclude": "high",
"forbid": "high",
"invalidate": "high",
"issue": "high",
"rotate": "medium",
}
# Severity ordering for cap comparison