feat(intel): attacker_intel table + repo helpers

New TTL-cached threat-intel row keyed by attacker IP, with per-provider
verdict/raw/queried_at columns for GreyNoise, AbuseIPDB, abuse.ch Feodo
Tracker and ThreatFox. Carries schema_version from day one (federation
wire-format precedent set by SessionProfile). Repo gains
upsert_attacker_intel, get_attacker_intel_by_ip, and a
get_unenriched_attacker_ips backfill primitive that picks fresh + stale
rows for the forthcoming 'decnet enrich' worker.

Also documents the open-source intel-source backlog in DEVELOPMENT_V2.
This commit is contained in:
2026-04-26 04:56:47 -04:00
parent 9816cdbd53
commit 0dd3811436
7 changed files with 339 additions and 0 deletions

View File

@@ -278,6 +278,28 @@ class BaseRepository(ABC):
"""Retrieve the keystroke-dynamics profile row for a session."""
pass
@abstractmethod
async def upsert_attacker_intel(self, data: dict[str, Any]) -> str:
"""Insert or update the threat-intel row for an attacker IP.
``data`` MUST include ``attacker_ip`` and ``expires_at``. Returns
the row UUID. Used by the ``decnet enrich`` worker.
"""
pass
@abstractmethod
async def get_attacker_intel_by_ip(self, ip: str) -> Optional[dict[str, Any]]:
"""Return the threat-intel row for ``ip`` or ``None`` if missing."""
pass
@abstractmethod
async def get_unenriched_attacker_ips(self, limit: int = 100) -> list[str]:
"""List attacker IPs with no intel row OR whose row is past expires_at.
Used by the enrich worker to backfill on startup and on each wake.
"""
pass
@abstractmethod
async def increment_smtp_target(self, attacker_uuid: str, domain: str) -> None:
"""