fix(ttp): correct stale clip tests to ceiling semantics + document ATTACKER_FINGERPRINTED topic
confidence_max is a ceiling (min(base, ceiling)), not a multiplier — the ASVS pass fixed this (BUG-8: min(base, base*ceiling) -> min(base, ceiling)), but 4 lifter clip tests still encoded the old base*ceiling math (0.45/0.4/ 0.35) and were masked by the make test-web bundle error fail-fast. All four now assert the 0.5 ceiling. Separately, test_topics_matches_documented_set lacked attacker.fingerprinted, which worker.py legitimately subscribes to (JARM/HASSH/tcpfp/ipv6_leak -> TTP tagging). Located via turbovec + git pickaxe. (cherry picked from commit f83b467c35649a06fa36f4b350e6666379cd71cb)
This commit is contained in:
@@ -220,11 +220,12 @@ def test_clipped_state_caps_confidence() -> None:
|
||||
out = asyncio.run(lifter.tag(
|
||||
_ev("session", {"beacon_interval_s": 60, "beacon_jitter_pct": 0.05}),
|
||||
))
|
||||
# Base confidences in YAML are 0.8 and 0.85; clipped to 0.5 ceiling
|
||||
# → 0.4 and 0.425 respectively.
|
||||
# Base confidences in YAML are 0.8 and 0.85; a clipped state caps each
|
||||
# at the 0.5 ceiling — min(base, 0.5) = 0.5. confidence_max is a ceiling,
|
||||
# not a multiplier (BUG-8 in the ASVS hardening pass).
|
||||
assert out
|
||||
for tag in out:
|
||||
assert tag.confidence < 0.5
|
||||
assert tag.confidence == pytest.approx(0.5)
|
||||
|
||||
|
||||
def test_expired_state_treated_as_disabled() -> None:
|
||||
|
||||
@@ -179,8 +179,8 @@ def test_clipped_rule_caps_confidence() -> None:
|
||||
"credential_hash": "x", "reuse_count": 3,
|
||||
})))
|
||||
assert len(out) == 1
|
||||
# Base 0.9 × 0.5 ceiling.
|
||||
assert out[0].confidence == pytest.approx(0.45)
|
||||
# Base 0.9 capped at the 0.5 ceiling — min(0.9, 0.5).
|
||||
assert out[0].confidence == pytest.approx(0.5)
|
||||
|
||||
|
||||
# ── Ownership predicate ─────────────────────────────────────────────
|
||||
|
||||
@@ -114,8 +114,8 @@ def test_clipped_rule_caps_confidence() -> None:
|
||||
payload = {"shared_password_hash": "x", "account_count": 9}
|
||||
out = asyncio.run(lifter.tag(_ev(payload)))
|
||||
assert len(out) == 1
|
||||
# Base confidence 0.9 × 0.5 ceiling clamp.
|
||||
assert out[0].confidence == pytest.approx(0.45)
|
||||
# Base confidence 0.9 capped at the 0.5 ceiling — min(0.9, 0.5).
|
||||
assert out[0].confidence == pytest.approx(0.5)
|
||||
|
||||
|
||||
def test_expired_rule_does_not_fire() -> None:
|
||||
|
||||
@@ -423,9 +423,11 @@ def test_clipped_intel_rule_caps_confidence() -> None:
|
||||
"abuseipdb_score": 100,
|
||||
"abuseipdb_categories": [18],
|
||||
})))
|
||||
# Bases are 0.6–0.7; a clipped state caps each at the 0.5 ceiling —
|
||||
# min(base, 0.5) = 0.5 (confidence_max is a ceiling, not a multiplier).
|
||||
assert out
|
||||
for tag in out:
|
||||
assert tag.confidence <= 0.35 + 1e-6
|
||||
assert tag.confidence == pytest.approx(0.5)
|
||||
|
||||
|
||||
# ── Decoupling guard (behavioral counterpart of E.2.7 static check) ─
|
||||
|
||||
@@ -170,6 +170,7 @@ def test_topics_matches_documented_set() -> None:
|
||||
_topics.attacker(_topics.ATTACKER_SESSION_ENDED),
|
||||
_topics.attacker(_topics.ATTACKER_OBSERVED),
|
||||
_topics.attacker(_topics.ATTACKER_INTEL_ENRICHED),
|
||||
_topics.attacker(_topics.ATTACKER_FINGERPRINTED),
|
||||
_topics.identity(_topics.IDENTITY_FORMED),
|
||||
_topics.identity(_topics.IDENTITY_MERGED),
|
||||
_topics.credential(_topics.CREDENTIAL_REUSE_DETECTED),
|
||||
|
||||
Reference in New Issue
Block a user