feat(ttp): E.3.3 repository — insert_tags + listing rollups (dual backend)
Dialect-split: portable rollup queries on TTPMixin; bulk insert with ON CONFLICT DO NOTHING / INSERT IGNORE in the per-dialect repos. Confidence-floor (< 0.3) drop applied at mixin layer before the dialect hook. BaseRepository now declares the six TTP methods abstract. Tests in tests/web/db/test_ttp_repo.py flipped from pytest.fail stubs to real dual-backend behavioral tests; tests/ttp/test_confidence.py drop-below-floor xfail removed.
This commit is contained in:
@@ -2,6 +2,12 @@ from abc import ABC, abstractmethod
|
||||
from typing import Any, Optional
|
||||
|
||||
from decnet.web.db.models.topology import DeckyRow, EdgeRow, LANRow, TopologySummary
|
||||
from decnet.web.db.models import (
|
||||
CampaignTechniqueRow,
|
||||
IdentityTechniqueRow,
|
||||
TechniqueRollupRow,
|
||||
TTPTag,
|
||||
)
|
||||
|
||||
|
||||
class BaseRepository(ABC):
|
||||
@@ -1300,3 +1306,49 @@ class BaseRepository(ABC):
|
||||
|
||||
async def count_probe_relays(self, attacker_ip: str, decky: str) -> int:
|
||||
raise NotImplementedError
|
||||
|
||||
# -------------------- TTP tagging (E.3.3) --------------------
|
||||
|
||||
@abstractmethod
|
||||
async def insert_tags(self, rows: list[TTPTag]) -> int:
|
||||
"""Bulk-upsert ``ttp_tag`` rows with ``INSERT OR IGNORE`` semantics.
|
||||
|
||||
Drops rows with ``confidence < 0.3`` (the floor pinned in
|
||||
``tests/ttp/test_confidence.py``). Returns the count of rows
|
||||
actually written. Idempotent — replaying the same source events
|
||||
converges to the same tag set without duplicates.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
async def list_techniques_by_identity(
|
||||
self, uuid: str,
|
||||
) -> list[IdentityTechniqueRow]:
|
||||
"""Per-Identity TTP rollup (joins through ``Attacker.identity_id``)."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
async def list_techniques_by_attacker(
|
||||
self, uuid: str,
|
||||
) -> list[IdentityTechniqueRow]:
|
||||
"""Per-Attacker (per-IP) TTP rollup; excludes identity-rollup tags."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
async def list_techniques_by_campaign(
|
||||
self, uuid: str,
|
||||
) -> list[CampaignTechniqueRow]:
|
||||
"""Campaign-wide TTP rollup across member identities."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
async def list_techniques_by_session(
|
||||
self, sid: str,
|
||||
) -> list[IdentityTechniqueRow]:
|
||||
"""Session-scoped TTP timeline."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
async def list_distinct_techniques(self) -> list[TechniqueRollupRow]:
|
||||
"""Fleet-wide distinct-technique rollup."""
|
||||
raise NotImplementedError
|
||||
|
||||
Reference in New Issue
Block a user