● Zion Boggan
repos/Sightline/backend/app/services/enrichment/base.py
zionboggan.com ↗
57 lines · python
History for this file →
1
"""Uniform enricher contract. Every OSINT module returns the same envelope so the platform
2
can store entities, relationships, evidence, source metadata, confidence and the raw response
3
reference identically regardless of source."""
4
from __future__ import annotations
5
 
6
from abc import ABC, abstractmethod
7
from dataclasses import asdict, dataclass, field
8
from datetime import datetime, timezone
9
 
10
 
11
@dataclass
12
class EnrichEntity:
13
    kind: str
14
    value: str
15
    attributes: dict = field(default_factory=dict)
16
 
17
 
18
@dataclass
19
class EnrichRelationship:
20
    src_kind: str
21
    src_value: str
22
    dst_kind: str
23
    dst_value: str
24
    relation: str
25
    confidence: float = 0.7
26
 
27
 
28
@dataclass
29
class EnrichResult:
30
    enricher: str
31
    target: str
32
    entities: list[EnrichEntity] = field(default_factory=list)
33
    relationships: list[EnrichRelationship] = field(default_factory=list)
34
    evidence: list[dict] = field(default_factory=list)
35
    source_metadata: dict = field(default_factory=dict)
36
    confidence: float = 0.5
37
    raw_response: object | None = None
38
    error: str | None = None
39
    fetched_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
40
 
41
    def to_dict(self) -> dict:
42
        d = asdict(self)
43
        d.pop("raw_response", None)
44
        return d
45
 
46
 
47
class BaseEnricher(ABC):
48
    name: str = "base"
49
    kind: str = "generic"
50
    requires_network: bool = True
51
 
52
    @abstractmethod
53
    def run(self, target: str) -> EnrichResult:
54
        ...
55
 
56
    def _empty(self, target: str, error: str | None = None) -> EnrichResult:
57
        return EnrichResult(enricher=self.name, target=target, error=error, confidence=0.0)