Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 10 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/alembic.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# ©AngelaMos | 2026
# alembic.ini
#
# Alembic database migration configuration
#
# Points script_location to the alembic/ directory and sets
# the default asyncpg connection URL (overridden at runtime
# by env.py from settings). Configures Python logging with
# WARN level for root and sqlalchemy.engine, INFO for
# alembic, all routed to a stderr console handler with
# generic format. Connects to alembic/env.py,
# alembic/versions/, app/config

[alembic]
script_location = alembic
Expand Down
15 changes: 15 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
"""
©AngelaMos | 2026
env.py

Alembic migration environment with async PostgreSQL engine
support

Configures SQLModel.metadata as the target for autogenerate,
imports model registrations (ModelMetadata, ThreatEvent) to
ensure table definitions are available. run_migrations_
offline generates SQL scripts without a connection. run_
migrations_online creates an async engine with NullPool and
executes migrations via run_sync. Mode is selected based on
context.is_offline_mode()

Connects to:
app/config - settings.database_url
app/models - SQLModel table registrations
"""

import asyncio
Expand Down
9 changes: 9 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
"""
©AngelaMos | 2026
__main__.py

Uvicorn entry point for the AngelusVigil API server

Launches app.main:app via uvicorn using host, port, and
reload settings from app.config.settings

Connects to:
config.py - settings.host, settings.port, settings.debug
main.py - ASGI application instance
"""

import uvicorn
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""
©AngelaMos | 2026
__init__.py

API package containing FastAPI route modules for health,
ingest, threats, stats, models, and websocket endpoints
"""
14 changes: 14 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/api/deps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
"""
©AngelaMos | 2026
deps.py

FastAPI dependency injection providers for API key
authentication and async database sessions

require_api_key checks the X-API-Key header against
settings.api_key, returning 401 if mismatched (no-op
when api_key is unconfigured). get_session yields an
AsyncSession from the app-level session_factory stored
on app.state during lifespan initialization

Connects to:
config.py - settings.api_key
factory.py - app.state.session_factory
api/ - injected via Depends() in route handlers
"""

from collections.abc import AsyncIterator
Expand Down
15 changes: 15 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/api/health.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
"""
©AngelaMos | 2026
health.py

Health and readiness probe endpoints for container
orchestration

GET /health returns liveness status with uptime_seconds
and pipeline_running flag. GET /ready checks database
connectivity (SELECT 1) and Redis ping, reports
models_loaded status, and returns 503 if any dependency
is down. Both endpoints read from app.state set during
lifespan

Connects to:
factory.py - app.state.startup_time,
pipeline_running, db_engine
core/redis_manager - redis_manager.ping()
"""

import time
Expand Down
15 changes: 15 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/api/ingest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
"""
©AngelaMos | 2026
ingest.py

Batch log ingestion endpoint for pushing raw log lines
into the detection pipeline

POST /ingest/batch accepts a BatchIngestRequest (list of
raw log line strings), pushes each into the pipeline's
raw_queue via put_nowait, stops on QueueFull, and returns
the count of successfully queued lines. Protected by
require_api_key dependency

Connects to:
deps.py - require_api_key
core/ingestion/
pipeline.py - pipeline.raw_queue
factory.py - app.state.pipeline
"""

import asyncio
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
"""
©AngelaMos | 2026
models_api.py

ML model status and retraining endpoints

GET /models/status returns models_loaded flag, detection
_mode (hybrid or rules), and active model metadata from
the database. POST /models/retrain dispatches a
background retraining job that loads stored ThreatEvents,
labels them using review_label or score thresholds
(SCORE_ATTACK_THRESHOLD 0.5, SCORE_NORMAL_CEILING 0.3),
supplements with synthetic data if below MIN_TRAINING_
SAMPLES (200), runs TrainingOrchestrator, and writes
model metadata. _fallback_synthetic spawns a subprocess
CLI train command when no real events exist

Connects to:
config.py - settings.model_dir, ensemble
weights
models/model_metadata - ModelMetadata queries
models/threat_event - ThreatEvent training data
ml/orchestrator - TrainingOrchestrator
ml/synthetic - generate_mixed_dataset
cli/main - _write_metadata
"""

import logging
Expand Down
13 changes: 13 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/api/stats.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
"""
©AngelaMos | 2026
stats.py

Threat statistics endpoint returning aggregated metrics
for a configurable time window

GET /stats accepts a range query parameter (default
"24h") and delegates to stats_service.get_stats for
database aggregation, returning a StatsResponse

Connects to:
deps.py - get_session dependency
schemas/stats - StatsResponse model
services/stats_
service - get_stats business logic
"""

from fastapi import APIRouter, Depends, Query
Expand Down
17 changes: 17 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/api/threats.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
"""
©AngelaMos | 2026
threats.py

Threat event CRUD endpoints with filtering and
pagination

GET /threats lists events with optional severity,
source_ip, since/until datetime filters, and limit/
offset pagination (max 100). GET /threats/{threat_id}
fetches a single event by UUID, returning 404 if not
found. Both delegate to threat_service for database
queries

Connects to:
deps.py - get_session dependency
schemas/threats - ThreatEventResponse,
ThreatListResponse
services/threat_
service - get_threats, get_threat_by_id
"""

import uuid
Expand Down
16 changes: 16 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/api/websocket.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
"""
©AngelaMos | 2026
websocket.py

WebSocket endpoint streaming real-time threat alerts via
Redis pub/sub relay

WS /ws/alerts accepts a client connection, subscribes to
the ALERTS_CHANNEL via a per-client Redis pubsub instance,
and runs two concurrent tasks: _relay forwards published
messages as WebSocket text frames, _receive drains client
messages until disconnect. asyncio.wait with FIRST_
COMPLETED cancels the other task on disconnect, then
unsubscribes and closes the pubsub. Per-client subscribers
ensure correct multi-worker behavior

Connects to:
core/alerts - ALERTS_CHANNEL constant
core/redis_manager- redis_manager.client
"""

import asyncio
Expand Down
21 changes: 21 additions & 0 deletions PROJECTS/advanced/ai-threat-detection/backend/app/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
"""
©AngelaMos | 2026
config.py

Pydantic-settings application configuration loaded from
environment variables and .env file

Defines the Settings model with defaults for: server
(host 0.0.0.0, port 8000, debug, log_level), database
(postgresql+asyncpg URL), Redis URL, GeoIP MaxMind
database path, nginx log path, pipeline queue sizes
(raw 1000, parsed 500, feature 200, alert 100), batch
settings (size 32, timeout 50ms), and ML configuration
(model_dir, detection_mode, ensemble weights for
autoencoder/random-forest/isolation-forest at 0.40/0.40
/0.20, ae_threshold_percentile 99.5, MLflow tracking
URI). Exports a module-level singleton settings instance

Connects to:
factory.py - consumed in lifespan and create_app
__main__.py - server host/port/reload
core/ingestion/ - queue sizes, log path
core/detection/ - model_dir, ensemble weights
core/enrichment/ - geoip_db_path
"""

from pydantic_settings import BaseSettings, SettingsConfigDict
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""
©AngelaMos | 2026
__init__.py

Core package containing detection, ingestion, feature
engineering, enrichment, and alert subsystems
"""
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""
©AngelaMos | 2026
__init__.py

Alerts package defining the ALERTS_CHANNEL constant for
Redis pub/sub real-time threat notification
"""

ALERTS_CHANNEL = "alerts"
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
"""
©AngelaMos | 2026
dispatcher.py

Alert dispatcher routing scored threat events to storage,
Redis pub/sub, and structured logging

AlertDispatcher.dispatch receives a ScoredRequest from the
pipeline, classifies severity via classify_severity, logs
every event, and for MEDIUM+ severity persists to
PostgreSQL via create_threat_event and publishes a
WebSocketAlert JSON payload to the ALERTS_CHANNEL for
real-time WebSocket relay

Connects to:
core/alerts/__init__ - ALERTS_CHANNEL
core/detection/
ensemble - classify_severity
core/ingestion/
pipeline - ScoredRequest dataclass
schemas/websocket - WebSocketAlert model
services/threat_
service - create_threat_event
"""

import logging
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""
©AngelaMos | 2026
__init__.py

Detection package containing the rule engine, ONNX
inference engine, and ensemble scoring utilities
"""
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
"""
©AngelaMos | 2026
ensemble.py

Score normalization, fusion, and severity classification
utilities for the ML ensemble

normalize_ae_score maps autoencoder reconstruction error
to [0,1] using 2x threshold scaling. normalize_if_score
inverts sklearn isolation forest scores to [0,1].
fuse_scores computes a weighted average across available
model scores. blend_scores combines ML ensemble and rule
engine scores with configurable ml_weight (default 0.7).
classify_severity maps unified score to HIGH (>=0.7),
MEDIUM (>=0.5), or LOW

Connects to:
core/detection/
inference - raw model scores passed to normalizers
core/detection/
rules - classify_severity used for rule results
core/ingestion/
pipeline - fuse_scores and blend_scores in
scoring stage
"""


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
"""
©AngelaMos | 2026
inference.py

ONNX-based inference engine for the 3-model ML ensemble

InferenceEngine loads autoencoder (ae.onnx), random
forest (rf.onnx), and isolation forest (if.onnx) sessions
plus RobustScaler parameters (scaler.json) and anomaly
threshold (threshold.json) from a model directory. predict
runs all 3 models on a batch of feature vectors: applies
_scale_for_ae to normalize autoencoder input, computes
reconstruction MSE for ae scores, extracts attack
probability from skl2onnx RF output format via _extract_
rf_proba, and returns raw IF decision scores. Returns
None when models are unavailable. Each ONNX session uses
single-threaded execution (inter/intra_op_num_threads=1)

Connects to:
config.py - settings.model_dir
factory.py - _load_inference_engine at startup
core/ingestion/
pipeline - batch inference in scoring stage
ml/export_onnx - produces the ONNX model files
"""

import json
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
"""
©AngelaMos | 2026
rules.py

Cold-start rule-based detection engine inspired by
ModSecurity Core Rule Set

RuleEngine.score_request evaluates requests against 7
regex-based _PatternRules (LOG4SHELL 0.95, COMMAND_
INJECTION 0.90, SQL_INJECTION 0.85, XSS 0.80, FILE_
INCLUSION 0.75, SSRF 0.70, PATH_TRAVERSAL 0.60),
double-encoding detection (0.40), scanner user-agent
signature matching (0.35), and 2 _ThresholdRules
(RATE_ANOMALY >100 req/min 0.30, HIGH_ERROR_RATE >50%
0.25). Final score takes the highest match plus 0.05
boost per additional rule, capped at 1.0. Returns a
RuleResult with threat_score, severity, matched_rules,
and component_scores

Connects to:
core/features/
patterns - compiled regex patterns (SQLI,
XSS, LOG4SHELL, etc.)
core/features/
signatures - SCANNER_USER_AGENTS list
core/detection/
ensemble - classify_severity
core/ingestion/
parsers - ParsedLogEntry
"""

import re
Expand Down
Loading
Loading