feat(cookie): Pro-Cookie-Library-Abgleich (2287er OCD + 35er rich) + Panel
- analyze_cookies gleicht Cookies gegen BEIDE Libraries ab: compliance.cookie_library
(2287, OCD/CC0 — Kategorie/Retention) + 35er rich-DB (technical_necessity/reid/
schrems/eu_alternative). 5 Befund-Typen: tracker_as_necessary, missing_purpose,
excessive_lifetime (Art.5), third_country (Art.44), eu_alternative (kommerziell).
- Endpoint GET /snapshots/{id}/cookie-check (load_big_library batch + analyze).
- Frontend CookieLibraryPanel im Snapshot-Detail.
- Fix CookieResultView: Zweck nicht mehr auf 60 Zeichen gekuerzt; Rolle 'unknown'
als Strich statt 'Unbekannt'.
Tests: 7 backend + frontend vitest gruen.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
"""Pro-Cookie-Library-Abgleich: deklariert vs. cookie_knowledge_db."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from compliance.services.cookie_library_check import analyze_cookies
|
||||
|
||||
|
||||
def test_tracker_declared_necessary_is_high_finding():
|
||||
# _ga ist laut Library technical_necessity=none, reid=high.
|
||||
vendors = [{
|
||||
"name": "Salesforce", "category": "necessary",
|
||||
"cookies": [{"name": "_ga", "purpose": "Funktionsverbesserung"}],
|
||||
}]
|
||||
out = analyze_cookies(vendors)
|
||||
assert out["summary"]["in_library"] == 1
|
||||
f = out["findings"][0]
|
||||
assert f["type"] == "tracker_as_necessary"
|
||||
assert f["severity"] == "HIGH"
|
||||
assert "§ 25" in f["remediation"]
|
||||
assert f["library_purpose"] # exact_purpose aus Library
|
||||
|
||||
|
||||
def test_missing_purpose_when_library_knows_it():
|
||||
vendors = [{
|
||||
"name": "X", "category": "marketing",
|
||||
"cookies": [{"name": "_ga", "purpose": ""}],
|
||||
}]
|
||||
out = analyze_cookies(vendors)
|
||||
f = out["findings"][0]
|
||||
assert f["type"] == "missing_purpose"
|
||||
assert f["severity"] == "MEDIUM"
|
||||
assert f["library_purpose"]
|
||||
|
||||
|
||||
def test_unknown_cookie_no_finding():
|
||||
vendors = [{
|
||||
"name": "Y", "category": "necessary",
|
||||
"cookies": [{"name": "completely_unknown_xyz_123", "purpose": ""}],
|
||||
}]
|
||||
out = analyze_cookies(vendors)
|
||||
assert out["summary"]["checked"] == 1
|
||||
assert out["summary"]["in_library"] == 0
|
||||
assert out["findings"] == []
|
||||
|
||||
|
||||
def _types(out):
|
||||
return {f["type"] for f in out["findings"]}
|
||||
|
||||
|
||||
def test_third_country_and_eu_alternative_for_us_tracker():
|
||||
# _ga: US-Vendor + EU-Alternative Matomo in der Library.
|
||||
out = analyze_cookies([{
|
||||
"name": "Google", "category": "marketing",
|
||||
"cookies": [{"name": "_ga", "purpose": "Statistik", "expiry": "2 Jahre"}],
|
||||
}])
|
||||
t = _types(out)
|
||||
assert "third_country" in t
|
||||
assert "eu_alternative" in t
|
||||
|
||||
|
||||
def test_third_country_deduped_per_vendor():
|
||||
out = analyze_cookies([{
|
||||
"name": "Google", "category": "marketing",
|
||||
"cookies": [
|
||||
{"name": "_ga", "purpose": "x", "expiry": "2 Jahre"},
|
||||
{"name": "_gid", "purpose": "x", "expiry": "1 Tag"},
|
||||
],
|
||||
}])
|
||||
assert sum(1 for f in out["findings"] if f["type"] == "third_country") == 1
|
||||
|
||||
|
||||
def test_excessive_lifetime():
|
||||
# _gid: typische Laufzeit 24 Stunden; deklariert 2 Jahre.
|
||||
out = analyze_cookies([{
|
||||
"name": "Google", "category": "marketing",
|
||||
"cookies": [{"name": "_gid", "purpose": "x", "expiry": "2 Jahre"}],
|
||||
}])
|
||||
el = [f for f in out["findings"] if f["type"] == "excessive_lifetime"]
|
||||
assert el and "Art. 5" in el[0]["remediation"]
|
||||
|
||||
|
||||
def test_big_library_covers_cookie_not_in_rich_db():
|
||||
# Cookie nicht in der 35er rich-DB, aber in der grossen 2287er (big_lib).
|
||||
big = {"bmw_track_de": {
|
||||
"actual_category": "marketing", "typical_max_age_seconds": 86400,
|
||||
"purpose_de": "Reichweiten-Tracking", "vendor_name": "BMW",
|
||||
}}
|
||||
out = analyze_cookies([{
|
||||
"name": "BMW", "category": "necessary",
|
||||
"cookies": [{"name": "bmw_track_de", "purpose": "", "expiry": "2 Jahre"}],
|
||||
}], big)
|
||||
assert out["summary"]["in_library"] == 1
|
||||
t = {f["type"] for f in out["findings"]}
|
||||
assert "tracker_as_necessary" in t # actual_category=marketing → Tracker
|
||||
assert "excessive_lifetime" in t # 2 Jahre vs. 1 Tag
|
||||
Reference in New Issue
Block a user