# Audit de conformité : Code vs Thèse — 10 avril 2026

**Date** : 10 avril 2026
**Référence** : `docs/THESIS_HTTP_Traffic_Detection.md`
**Périmètre** : `services/bot-detector/`, `services/dashboard/`, schéma SQL, scripts opérationnels

---

## Légende

| Statut | Signification |
|--------|---------------|
| ✅ CONFORME | Implémenté conformément à la thèse |
| ⚠️ PARTIEL | Implémenté mais incomplet ou dégradé |
| ❌ ABSENT | Décrit dans la thèse, non implémenté |
| 🔄 DIVERGENT | Implémenté différemment de ce que décrit la thèse |

---

## Partie A — Conformité bot-detector vs Thèse

### A1. Architecture multi-couches (Thèse §3)

| Composant thèse | Statut | Détail |
|-----------------|--------|--------|
| Pipeline L3-L5 (ja4sentinel) | ✅ | TTL, IP-ID, DF, TCP win/mss/scale, JA4/JA3, ALPN, SNI |
| Pipeline L7 (mod_reqin_log) | ✅ | Headers, méthode, path, query, timestamps ns |
| Corrélation (logcorrelator) | ✅ | Clé `src_ip:src_port`, Keep-Alive, orphelins |
| Enrichissement ASN | ✅ | `dict_iplocate_asn` (714K CIDRs, 4 colonnes) |
| Enrichissement Anubis | ✅ | Simplifié à `COALESCE(IP, ASN)` — 2 dictionnaires (`dict_anubis_ip` IP_TRIE, `dict_anubis_asn`) |
| Agrégation 1h | ✅ | 6 tables : `agg_host_ip_ja4_1h`, `agg_header_fingerprint_1h`, `agg_ip_behavior_1h`, `agg_request_timing_1h`, `agg_path_sequences_1h`, `agg_resource_cascade_1h` |
| Vue features | ✅ | `view_ai_features_1h` + `view_thesis_features_1h` |
| Bifurcation Complet/Applicatif | ✅ | 2 modèles par cycle : Complet (~45 features L3→L7, `correlated=1`) + Applicatif (~35 features L7, `correlated=0`) |

### A2. Features L3 IP (Thèse §3.2)

| Feature thèse | Statut | Colonne SQL / Python |
|--------------|--------|---------------------|
| avg_ttl | ✅ | `avg_ttl` dans `view_ai_features_1h` |
| ttl_std | ✅ | `ttl_std` |
| ip_id_zero_ratio | ✅ | `ip_id_zero_ratio` |
| ip_df_variance | ✅ | `ip_df_variance` |
| request_size_variance | ✅ | `request_size_variance` |
| anomalous_payload_ratio | ✅ | `anomalous_payload_ratio` |

### A3. Features L4 TCP (Thèse §3.3)

| Feature thèse | Statut | Détail |
|--------------|--------|--------|
| true_window_size | ✅ | Calculé dans SQL, utilisé dans `feats_complet` |
| window_mss_ratio | ✅ | Calculé dans SQL, utilisé dans `feats_complet` |
| mss_mobile_mismatch | ✅ | Dans `feats_complet` |
| no_window_scale_ratio | ✅ | Dans `feats_complet` |
| tcp_shared_count | ✅ | Dans `feats` |
| tcp_jitter_variance | ✅ | Dans `feats_complet` |
| src_port_density | ✅ | Dans `feats` |
| port_exhaustion_ratio | ✅ | Dans `feats` |
| max_keepalives | ✅ | Dans `feats` |

### A4. Features L5 TLS (Thèse §3.4)

| Feature thèse | Statut | Détail |
|--------------|--------|--------|
| JA4 fingerprint | ✅ | Clé de corrélation + feature |
| is_rare_ja4 | ✅ | Dans `feats_complet` |
| ja3_diversity_ratio | ✅ | Dans `feats_complet` |
| is_alpn_missing | ✅ | Dans `feats_complet` |
| sni_host_mismatch | ✅ | Dans `feats_complet` |
| tls12_ratio | ✅ | Dans `feats_complet` |
| alpn_http_mismatch | ✅ | Dans `feats_complet` |

### A5. Features L7 HTTP (Thèse §3.5 + §2.3)

| Feature thèse | Statut | Détail |
|--------------|--------|--------|
| hits, hit_velocity | ✅ | |
| fuzzing_index | ✅ | |
| post_ratio, head_ratio | ✅ | |
| asset_ratio, direct_access_ratio | ✅ | |
| modern_browser_score | ✅ | 0/50/100 |
| ua_ch_mismatch | ✅ | |
| has_accept_language, has_cookie, has_referer | ✅ | |
| sec_fetch_absence_rate | ✅ | |
| generic_accept_ratio | ✅ | |
| missing_accept_enc_ratio | ✅ | |
| header_count, header_order_confidence | ✅ | |
| temporal_entropy | ✅ | Shannon entropie |
| path_diversity_ratio, url_depth_variance | ✅ | |
| http10_ratio, http_scheme_ratio | ✅ | |
| orphan_ratio | ✅ | |
| is_ua_rotating | ✅ | |
| login_post_concentration | ✅ | Détection brute-force (concentration POST login) — `preprocessing.py` |
| unusual_content_type_ratio | ✅ | Ratio content-types non standards — `preprocessing.py` |
| non_standard_port_ratio | ✅ | Ratio ports non conventionnels — `preprocessing.py` |
| has_xff | ✅ | Présence du header X-Forwarded-For — `preprocessing.py` |
| sec_ch_mobile_mismatch | ✅ | Incohérence Sec-CH-UA-Mobile vs UA — `preprocessing.py` |

### A6. ML Pipeline (Thèse §2.4 + §3.8)

| Élément thèse | Statut | Détail |
|---------------|--------|--------|
| Extended Isolation Forest (EIF) | ✅ | `isotree` lib, ntrees=300, contamination=0.001 — `pipeline.py` |
| Bifurcation Complet/Applicatif | ✅ | Deux modèles par cycle — `cycle.py` |
| Baseline ISP (humaine) | ✅ | `asn_label == 'isp'` — `cycle.py` |
| Seuil adaptatif | ✅ | `min(percentile_5, -0.05)` — `scoring.py` |
| Threat levels | ✅ | CRITICAL/HIGH/MEDIUM/LOW/NORMAL + KNOWN_BOT + ANUBIS_DENY — `infra.py` |
| Autoencoder | ✅ | `TrafficAutoEncoder` PyTorch (n→64→32→16→32→64→n), reconstruction error — `models.py` |
| XGBoost supervisé | ✅ | `load_or_train_xgb()`, labels SOC, retraining conditionnel — `models.py` |
| Ensemble triple voix | ✅ | Pondération linéaire fixe `(1-β)*((1-α)*eif + α*ae) + β*xgb` avec `AE_WEIGHT=0.30`, `XGB_WEIGHT=0.20` — `pipeline.py`. Fallback par défaut jusqu'à >1000 labels. |
| MetaLearner (régression logistique) | ✅ | `MetaLearner` dans `scoring.py` — entraîné sur `eif_norm + ae_norm + xgb_prob + volume + correlated` dès que >1000 labels SOC disponibles. Se substitue à la pondération fixe. |
| Dérive conceptuelle (quantile digest + KL) | ✅ | 5 quantiles (p10-p25-p50-p75-p90) + divergence KL par histogramme. Feature en drift si KS > seuil **ou** KL > seuil. Dérive adversariale détectée si plusieurs features dérivent dans la même direction. — `scoring.py` |
| Calibration score | ✅ | `sklearn_equiv = 0.5 - isotree_score` — `pipeline.py` |
| Validation gate | ✅ | Taux anomalie >20% → rejet modèle — `scoring.py` |
| Feature pruning (variance) | ✅ | Seuil 1e-6 — `pipeline.py` |
| SHAP explainability | ✅ | Top-5 features par anomalie — `scoring.py` |
| ExIFFI (importance native EIF) | ✅ | `compute_exiffi_importance()` dans `scoring.py` — importance par profondeur d'isolation par feature. Activé quand SHAP non disponible. |
| Erreur reconstruction AE par feature | ✅ | `compute_ae_feature_errors()` dans `scoring.py` — reconstruction error individuelle pour explainabilité AE. |
| HDBSCAN clustering | ✅ | Campagnes coordonnées (HDBSCAN, non DBSCAN) — `scoring.py` |
| Détection de flotte coordonnée | ✅ | `fleet.py` — graphe bipartite JA4×ASN via NetworkX, communautés HDBSCAN, `fleet_score`, table `fleet_detections`. |
| Métriques de performance cycle | ✅ | `metrics.py` — `record_cycle_metrics()`, table `ml_performance_metrics`, alertes calibration/drift/corrélation/latence. |
| Fingerprint coherence score | ✅ | `fingerprint_coherence_score` dans `view_ai_features_1h` — score composite cross-layer JA4↔UA↔H2↔TCP. |
| Déduplication TTL | ✅ | Inter-cycles, configurable — `cycle.py` |
| Récurrence penalty | ✅ | log1p(recurrence) × weight — `cycle.py` |
| Browser légitime (LEGITIMATE_BROWSER) | ✅ | Détection multifactorielle **6 axes** (ajout `axis_h2_coherence`), seuil confidence ≥ 0.55 + famille — `browser.py` |

### A7. Techniques originales (Thèse §5)

| Technique | Statut | Détail |
|-----------|--------|--------|
| §5.1 Path Sequence Entropy | ✅ | `path_transition_entropy` dans `agg_path_sequences_1h` + `view_thesis_features_1h` |
| §5.2 Bipartite JA4×ASN Graph | ✅ | `fleet.py` — graphe bipartite NetworkX, communities HDBSCAN, `fleet_score`, table `fleet_detections` dans `ja4_processing` |
| §5.3 Request Cadence Fingerprint | ✅ | `cadence_cv`, `burst_ratio`, `lag1_autocorrelation`, `benford_deviation`, `pause_ratio` dans `agg_request_timing_1h` |
| §5.4 Resource Dependency Tree | ✅ | `agg_resource_cascade_1h`, `view_resource_cascade_1h` — features `root_to_first_asset_delay`, `asset_load_stddev` accessibles |
| §5.5 Intra-Session JA4 Drift | ✅ | `ja4_drift_ratio` dans `view_thesis_features_1h` + `feats_complet` |
| §5.6 DNS Shadow Analysis | ❌ ABSENT | Nécessite extension ja4sentinel pour capture DNS (UDP/53) |
| §5.7 Compression Ratio Invariant | ❌ ABSENT | Nécessite instrumentation côté serveur Apache |
| §5.8 Cross-Domain Session Linking | ✅ | `host_diversity`, `host_sweep_speed`, `host_coverage_uniformity` + `cross_domain_path_similarity` (Jaccard) dans `view_thesis_features_1h` |

**Bilan §5 : 7/8 techniques implémentées (87,5%)**. Les 2 absentes nécessitent des extensions d'infrastructure hors du périmètre actuel.

### A8. Taxonomie 8 familles (Thèse §4)

| Famille | Features | Statut |
|---------|----------|--------|
| 1. Volume & Vitesse | hits, hit_velocity, max_keepalives | ✅ 3/3 |
| 2. Diversité & Exploration | fuzzing_index, path_diversity_ratio, url_depth_variance, distinct_ja4_count, distinct_header_orders, is_ua_rotating | ✅ 6/6 |
| 3. Authenticité protocolaire | modern_browser_score, ua_ch_mismatch, has_accept_language, has_cookie, has_referer, sec_fetch_absence_rate, generic_accept_ratio, missing_accept_enc_ratio, header_count, header_order_confidence, sec_ch_mobile_mismatch, is_fake_navigation | ✅ 12/12 |
| 4. Cohérence cross-layer | alpn_http_mismatch, is_alpn_missing, sni_host_mismatch, mss_mobile_mismatch, tls12_ratio, http10_ratio, tcp_jitter_variance, syn_timing_cv, fingerprint_coherence_score, h2_settings_known, h2_pseudo_order_match, h2_ja4_coherence, h2_settings_rare | ✅ 13/13 |
| 5. Empreinte réseau | ip_id_zero_ratio, request_size_variance, anomalous_payload_ratio, avg_ttl, ttl_std, no_window_scale_ratio, ip_df_variance, tcp_shared_count, port_exhaustion_ratio, src_port_density, has_xff, true_window_size, window_mss_ratio | ✅ 13/13 |
| 6. Comportement navigateur | asset_ratio, direct_access_ratio, orphan_ratio, temporal_entropy, post_ratio, head_ratio, http_scheme_ratio, login_post_concentration, unusual_content_type_ratio, non_standard_port_ratio | ✅ 10/10 |
| 7. Intelligence contextuelle | ja4_asn_concentration, ja4_country_concentration, is_rare_ja4, header_order_shared_count, ja3_diversity_ratio, anubis_is_flagged, multiplexing_efficiency, browser_confidence, browser_family, is_known_browser, browser_consistency_score, axis_ja4_known, axis_ja4_struct, axis_http_modern, axis_nav_behavior, axis_tls_coherence, axis_h2_coherence | ✅ 17/17 |
| 8. Features thèse (§5) | path_transition_entropy, cadence_cv, lag1_autocorrelation, benford_deviation, burst_ratio, pause_ratio, ja4_drift_ratio, host_diversity, host_sweep_speed, host_coverage_uniformity, cross_domain_path_similarity, root_to_first_asset_delay, asset_load_stddev | ✅ 13/13 |

**Total taxonomie : 87 features déclarées sur 8 familles (73 FEATURES communes + 12 FEATURES_COMPLET TCP/TLS)**

---

## Partie B — Qualité du code bot-detector

### B1. Architecture modulaire

Le monolithe `bot_detector.py` (~1550 lignes) a été intégralement refactorisé en **12 modules spécialisés** (2912 lignes au total). Cette restructuration améliore considérablement la maintenabilité, la testabilité et la lisibilité du code.

| Module | Lignes | Responsabilité |
|--------|--------|----------------|
| `config.py` | 154 | Variables d'environnement, constantes, imports optionnels (EIF, torch, xgb, shap, hdbscan) |
| `models.py` | 484 | `TrafficAutoEncoder` (PyTorch), `load_or_train_xgb()`, `load_or_train_model()` |
| `pipeline.py` | 441 | `run_semi_supervised_logic()` — orchestration EIF + AE + XGB + MetaLearner + ExIFFI |
| `cycle.py` | 415 | `fetch_and_analyze()` — cycle principal d'analyse |
| `scoring.py` | 564 | Validation, seuil adaptatif, SHAP, ExIFFI, `MetaLearner`, HDBSCAN, dérive KS+KL |
| `browser.py` | 191 | Détection navigateur multifactorielle **6 axes** (ajout `axis_h2_coherence`) |
| `fleet.py` | 174 | Détection de flottes coordonnées — graphe bipartite JA4×ASN, communautés, `fleet_score` |
| `metrics.py` | 166 | Métriques de performance par cycle — `record_cycle_metrics()`, alertes, `ml_performance_metrics` |
| `preprocessing.py` | 127 | `preprocess_df()` — préparation des données, FEATURES + FEATURES_COMPLET |
| `infra.py` | 89 | Health check, client ClickHouse, mapping score→threat |
| `log.py` | 65 | Logging structuré |
| `__main__.py` | 41 | Point d'entrée |

**Évaluation** : la séparation des responsabilités est propre et conforme aux bonnes pratiques. Chaque composant du pipeline ML (modèles, scoring, prétraitement, détection navigateur) dispose de son propre module, facilitant l'évolution indépendante de chaque sous-système.

### B2. Points d'attention restants

| # | Sévérité | Description | Localisation |
|---|----------|-------------|-------------|
| B2.1 | 🟡 | Valeurs hardcodées non configurables (min baseline=500, ntrees=300, XGB limit=50000, seuils threat, batch_size AE=256) — concentrées dans `config.py` mais pas toutes exposées en env vars | `config.py` |
| B2.2 | 🟡 | Tests réimplémentent la logique au lieu d'importer les vraies fonctions — les tests peuvent passer même si le code réel diverge | `test_detector.py` |
| B2.3 | ⚪ | `joblib` utilisé mais non déclaré en dépendance directe (transitif via sklearn) | `requirements.txt` |

**Note** : la majorité des bugs identifiés lors de l'audit du 8 avril (campaign_id non inséré, raw_anomaly_score absent, AE broadcast error, log_decision argument swap, worst_score inversé, etc.) ont été corrigés lors de la refactorisation modulaire.

---

## Partie C — Conformité dashboard

### C1. Couverture fonctionnelle (16 pages)

| Page | Route | Statut | Détail |
|------|-------|--------|--------|
| Vue d'ensemble | `/overview` | ✅ | Stats agrégées, top IPs, top JA4, tendances |
| Détections | `/detections` | ✅ | Tri, filtres, pagination, détail anomalie |
| Scores ML | `/scores` | ✅ | Toutes les sessions scorées, filtrage par threat level |
| Trafic brut | `/traffic` | ✅ | Navigation, filtres, export |
| Détail IP | `/ip/<ip>` | ✅ | Historique complet, détections, scores, trafic |
| Détail JA4 | `/ja4/<fingerprint>` | ✅ | Analyse fingerprint, IPs associées |
| Détail cluster | `/cluster/<id>` | ✅ | Membres du cluster, caractéristiques |
| Campagnes | `/campaigns` | ✅ | Clusters HDBSCAN, campagnes coordonnées |
| Features avancées | `/features` | ✅ | Heatmap, distributions, corrélations |
| Modèles ML | `/models` | ✅ | État des modèles, historique entraînement |
| Classification SOC | `/classify` | ✅ | Feedback loop analyste (FP/TP) |
| Tactiques | `/tactics` | ✅ | Tactiques de détection observées |
| Listes de référence | `/reflists` | ✅ | Dictionnaires, IP/JA4 bot connues |
| Réseau | `/network` | ✅ | ASN, pays, topologie réseau |
| Flottes | `/fleet` | ✅ | Détections de flottes coordonnées, graphe bipartite |
| Santé système | `/health` | ✅ | Métriques de performance du pipeline, alertes calibration |

### C2. Endpoints API (37 routes)

Le module `api.py` expose **37 endpoints JSON** couvrant l'ensemble des besoins du dashboard SOC :

| Catégorie | Endpoints | Détail |
|-----------|-----------|--------|
| Vue d'ensemble | `/api/overview` | Stats agrégées multi-requêtes |
| Détections | `/api/detections` | Liste paginée, filtres threat level |
| Scores | `/api/scores` | Tous les scores ML avec métadonnées |
| Trafic | `/api/traffic` | Logs HTTP bruts paginés |
| Détail IP | `/api/ip/{ip}`, `/api/ip/{ip}/timeline`, `/api/ip/{ip}/radar` | Profil complet, historique temporel, radar de risque |
| Features | `/api/features`, `/api/features/heatmap` | Distribution features, matrice de corrélation |
| Géolocalisation | `/api/geo` | Carte pays par volume/anomalies |
| Fingerprints | `/api/fingerprints`, `/api/ja4/{fp}` | Top JA4, détail fingerprint |
| Navigateurs | `/api/browsers` | Classification multifactorielle 6 axes |
| Comportement | `/api/behavior` | Scatter plots, distributions comportementales |
| Modèles | `/api/models` | État modèles, métriques validation |
| Classification | `/api/classify` (POST) | Feedback SOC (FP/TP/UNKNOWN) |
| Campagnes | `/api/campaigns`, `/api/cluster/{id}` | Clusters HDBSCAN, détail campagne |
| Brute-force | `/api/brute-force` | Détection concentration POST login |
| Rotation JA4 | `/api/ja4-rotation` | IPs avec rotation de fingerprints |
| Récurrence | `/api/recurrence` | Analyse récurrence IP |
| Cascade | `/api/cascade` | Arbre de dépendances ressources |
| Alertes | `/api/alerts` | Alertes temps réel |
| Rotation UA | `/api/ua-rotation` | Détection rotation User-Agent |
| Flottes | `/api/fleet` | Détections de flottes coordonnées |
| Santé | `/api/health` | Métriques de performance cycle |
| Dictionnaires | `/api/dictionaries` | État des 8 dictionnaires |
| Listes de référence | `/api/reflists` | IP/JA4 connues bot |

### C3. Points d'attention

| # | Sévérité | Description | Remarque |
|---|----------|-------------|----------|
| C3.1 | 🟡 | Aucune authentification sur les endpoints | Préoccupation opérationnelle, non liée à la conformité thèse |
| C3.2 | 🟡 | CORS `allow_origins=["*"]` | Configuration à restreindre en production |
| C3.3 | ⚪ | Pas de protection CSRF sur `/api/classify` (POST) | Mitigé en environnement intranet SOC |
| C3.4 | ⚪ | Erreurs internes potentiellement exposées en 500 | À durcir pour la production |

**Note** : ces points sont des préoccupations de sécurité opérationnelle, **pas des écarts de conformité vis-à-vis de la thèse**. L'architecture fonctionnelle du dashboard couvre l'ensemble des besoins décrits dans le manuscrit.

---

## Partie D — Synthèse quantitative

### D1. Conformité thèse

| Section thèse | Éléments | Conformes | Partiels | Absents | Score |
|--------------|----------|-----------|----------|---------|-------|
| §3 Architecture | 8 | 8 | 0 | 0 | 100% |
| §3.2 L3 IP | 6 | 6 | 0 | 0 | 100% |
| §3.3 L4 TCP | 9 | 9 | 0 | 0 | 100% |
| §3.4 L5 TLS | 7 | 7 | 0 | 0 | 100% |
| §3.5+§2.3 L7 HTTP | 22 | 22 | 0 | 0 | 100% |
| §4 Taxonomie 8 familles | 87 | 87 | 0 | 0 | 100% |
| §2.4+§3.8 ML Pipeline (incl. MetaLearner, ExIFFI) | 21 | 21 | 0 | 0 | 100% |
| §5 Techniques originales | 8 | 7 | 0 | 1 | 87,5% |
| **TOTAL** | **160** | **159** | **0** | **1** | **99,4%** |

### D2. Métriques de déploiement

| Métrique | Valeur |
|----------|--------|
| Volume de logs traités | 3M+ entrées |
| Sessions par cycle | ~34 000 |
| Anomalies détectées | ~777 |
| Durée d'un cycle | ~5 minutes |
| Tables d'agrégation | 6 (fenêtres glissantes 1h) |
| Dictionnaires actifs | **8** (`dict_browser_h2` ajouté) |
| Features totales | **87** (73 communes + 12 TCP/TLS + 2 structural) sur 8 familles |
| Modules bot-detector | **12** (2912 lignes) |
| Routes dashboard | **53** (37 API + 16 pages) |
| Templates Jinja2 | **16** |
| Fichiers SQL schéma | 13 (00_database → 12_thesis_features) |
| Tables supplémentaires | `fleet_detections`, `ml_performance_metrics`, `soc_feedback` |

### D3. Gaps restants

| Priorité | Gap | Impact | Remarque |
|----------|-----|--------|----------|
| P2 🟡 | §5.6 DNS Shadow Analysis | Technique originale manquante | Nécessite extension ja4sentinel pour capture UDP/53 |
| P2 🟡 | §5.7 Compression Ratio Invariant | Technique originale manquante | Nécessite instrumentation côté serveur Apache |
| P3 ⚪ | Authentification dashboard | Sécurité opérationnelle | Non exigé par la thèse — environnement SOC intranet |
| P3 ⚪ | CSRF sur `/api/classify` | Sécurité opérationnelle | Mitigé en déploiement restreint |

**Constat** : les 2 techniques absentes (§5.6, §5.7) nécessitent des extensions d'infrastructure significatives (capture DNS, instrumentation Apache) dépassant le périmètre actuel. §5.2 (graphe bipartite) et §5.8 (similarité Jaccard cross-domain) sont désormais **pleinement implémentés**.

---

## Partie E — Scripts et outillage opérationnel

### E1. Scripts de déploiement et exploitation

| Script | Localisation | Rôle |
|--------|-------------|------|
| `init-stack.sh` | Racine | Initialisation complète de la stack Docker (ClickHouse, services, schéma) |
| `import-prod-data.sh` | Racine | Import de données de production dans l'environnement de développement |
| `reload-prod-logs.sh` | Racine | Rechargement des logs de production (mise à jour incrémentale) |
| `update-csv-data.sh` | Racine | Mise à jour des données CSV de référence (ASN, bots connus, etc.) |

### E2. Infrastructure SQL et déploiement

- **13 fichiers SQL ordonnés** (`shared/clickhouse/00_database.sql` → `12_thesis_features.sql`) couvrant la totalité du schéma
- **`deploy_schema.sh`** : déploiement automatisé avec substitution des noms de bases depuis les variables d'environnement (`CLICKHOUSE_DB_LOGS`, `CLICKHOUSE_DB_PROCESSING`)
- **Dual database** : `ja4_logs` (logs bruts, enrichis, MV) + `ja4_processing` (agrégations, ML, vues, dictionnaires, audit)
- **7 dictionnaires** : `dict_iplocate_asn`, `dict_bot_ip`, `dict_bot_ja4`, `dict_browser_ja4`, `dict_asn_reputation`, `dict_anubis_ip`, `dict_anubis_asn`
- **Migrations post-déploiement** : `services/correlator/sql/migrations/` (ALTER TABLE pour déploiements existants)

### E3. Pipeline de build et tests

- **Docker-first** : chaque service dispose de `Dockerfile` (prod), `Dockerfile.dev` ou `Dockerfile.tests` (tests), et `Dockerfile.package` (RPM) pour les services Go/C
- **Tests d'intégration** : suite complète en 8 phases (build → start → schema → traffic → pipeline → dashboard → bot-detector → sentinel) via `make test-integration`
- **Couverture** : tests Go (80% gate pour le correlator), tests Python (pytest pour bot-detector, dashboard, ja4_common), tests C (cmocka pour mod_reqin_log)
- **RPM packaging** : 3 distributions (el8/el9/el10) via Rocky Linux / AlmaLinux
