remove infra.md.example, infra.md is the source of truth

This commit is contained in:
Azreen Jamal
2026-03-03 03:06:13 +08:00
parent 1ad3033cc1
commit a3c6d09350
86 changed files with 17093 additions and 39 deletions

View File

@@ -0,0 +1,129 @@
"""Abstract base class and shared data structures for AYN detectors."""
from __future__ import annotations
import logging
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Optional
logger = logging.getLogger(__name__)
# ---------------------------------------------------------------------------
# Detection result
# ---------------------------------------------------------------------------
@dataclass
class DetectionResult:
"""A single detection produced by a detector.
Attributes
----------
threat_name:
Short identifier for the threat (e.g. ``"Trojan.Miner.XMRig"``).
threat_type:
Category string — ``VIRUS``, ``MALWARE``, ``SPYWARE``, ``MINER``,
``ROOTKIT``, ``HEURISTIC``, etc.
severity:
One of ``CRITICAL``, ``HIGH``, ``MEDIUM``, ``LOW``.
confidence:
How confident the detector is in the finding (0100).
details:
Human-readable explanation.
detector_name:
Which detector produced this result.
"""
threat_name: str
threat_type: str
severity: str
confidence: int
details: str
detector_name: str
# ---------------------------------------------------------------------------
# Abstract base
# ---------------------------------------------------------------------------
class BaseDetector(ABC):
"""Interface that every AYN detector must implement.
Detectors receive a file path (and optionally pre-read content / hash)
and return zero or more :class:`DetectionResult` instances.
"""
# ------------------------------------------------------------------
# Identity
# ------------------------------------------------------------------
@property
@abstractmethod
def name(self) -> str:
"""Machine-friendly detector identifier."""
...
@property
@abstractmethod
def description(self) -> str:
"""One-line human-readable summary."""
...
# ------------------------------------------------------------------
# Detection
# ------------------------------------------------------------------
@abstractmethod
def detect(
self,
file_path: str | Path,
file_content: Optional[bytes] = None,
file_hash: Optional[str] = None,
) -> List[DetectionResult]:
"""Run detection logic against a single file.
Parameters
----------
file_path:
Path to the file on disk.
file_content:
Optional pre-read bytes of the file (avoids double-read).
file_hash:
Optional pre-computed SHA-256 hex digest.
Returns
-------
list[DetectionResult]
Empty list when the file is clean.
"""
...
# ------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------
def _read_content(
self,
file_path: Path,
file_content: Optional[bytes],
max_bytes: int = 10 * 1024 * 1024,
) -> bytes:
"""Return *file_content* if provided, otherwise read from disk.
Reads at most *max_bytes* to avoid unbounded memory usage.
"""
if file_content is not None:
return file_content
with open(file_path, "rb") as fh:
return fh.read(max_bytes)
def _log(self, msg: str, *args) -> None:
logger.info("[%s] " + msg, self.name, *args)
def _warn(self, msg: str, *args) -> None:
logger.warning("[%s] " + msg, self.name, *args)
def _error(self, msg: str, *args) -> None:
logger.error("[%s] " + msg, self.name, *args)