============================================================
Mantis TODO  (updated 2026-05-21)
============================================================

-- DONE (archived) ----------------------------------------

[x] CSV rolling log with date-based filenames
[x] Migrate inference engine to ort-tract (pure Rust)
[x] Improve ML inference throughput under high load
[x] ML + Rule fusion decision layer (FusionEngine)
[x] Code audit: remove .unwrap() / eprintln() outside build.rs
[x] Frontend detection page
[x] GeoIP unbounded thread explosion (semaphore cap = 8)
[x] maxminddb DEBUG log flood (EnvFilter "maxminddb=warn")
[x] Frontend UnifiedAlert API alignment (detection.tsx, WebSocketProvider, config.ts, dashboard.tsx)
[x] Rule engine -> replaced entirely by Suricata daemon mode
    Removed: vectorscan, rusqlite, protolens, pcre2, byte_test/jump/extract,
             app-layer-protocol, threshold, QUIC parser, suppress list (SQLite).
    Replaced by: suricata daemon + veth mirror + EVE JSON unix socket.
    Suricata handles all signature matching; Mantis reads alerts via output.rs.
[x] Suricata EVE socket race condition (bind before spawn)
[x] af-packet block-size too small (32768 -> 131072)
[x] Suricata noisy rule categories (exclude emerging-info/policy/user_agents)
[x] suppress.conf: add known-benign SIDs (2013504 APT User-Agent etc.)

-- SHOULD DO (detection capability) ----------------------

[ ] TLS / JA3 fingerprint analysis
    Goal: detect encrypted malware C2 / beaconing without decryption.
    Step 1: add tls event type to suricata.yaml EVE outputs (extended: yes).
    Step 2: parse event_type == "tls" in output.rs -> extract ja3.hash, sni, cert info.
    Step 3: build JA3 whitelist (HashSet<String>) from observed normal traffic baseline.
    Step 4: alert on unknown JA3 hash + check cert anomalies (self-signed, expired, CN mismatch).
    Step 5: beacon detection -- low stddev of inter-connection interval to same dst_ip on 443.
    No model needed for steps 1-5; add dedicated classifier only if false-positive rate
    is unacceptable after baseline calibration.
    Files: detection/suricata/output.rs, detection/suricata/tls.rs (new),
           model/log/suricata.rs, model/error/suricata.rs

[ ] XDP active response (auto-block)
    Goal: block confirmed attacker IPs at kernel level (< 1 us per packet).
    Design: BPF_MAP_TYPE_LRU_HASH keyed by src IPv4/IPv6; XDP program checks map
    and returns XDP_DROP before any userspace processing.
    Trigger: FusionEngine fires a fusion or high-confidence ML alert -> insert src_ip
    into block map via userspace BPF map update API.
    Expiry: separate tokio task sweeps entries older than block_ttl_secs (config).
    API: POST /api/blacklist still works for manual entries; auto-block is additive.
    Files: ingress-ebpf/src/main.rs (map lookup + XDP_DROP),
           core/ebpf/xsk_manager.rs (map fd plumbing),
           detection/fusion.rs (trigger auto-block on high-confidence events)

-- SHOULD DO (runtime management) ------------------------

[ ] Account system + persistent lists
    Two SQLite files:
    static/db/app.db
      accounts  (id, username, password_hash, role, created_at)
      sessions  (token TEXT PK, account_id, expires_at)
      whitelist (id, ip_net TEXT, comment TEXT, created_at)
      blacklist (id, ip_net TEXT, action TEXT, comment TEXT, created_at)
    Migration: CREATE TABLE IF NOT EXISTS at startup in AppServices::init().
    File: core/infrastructure/app_db.rs (new)

[ ] HTTP API -- auth / accounts / lists / system
    All routes require Bearer token except POST /api/auth/login.
    Auth:      POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me
    Accounts:  GET/POST /api/accounts, PUT /api/accounts/:id/password, DELETE /api/accounts/:id
    Suppress:  GET/POST/DELETE /api/suppress  (writes suppress.conf + signals Suricata reload)
    Lists:     GET/POST/DELETE /api/whitelist, /api/blacklist
    System:    POST /api/system/restart
    Files: web/routes/{auth,accounts,lists,system}.rs, web/middleware/auth.rs

[ ] Graceful restart
    Trigger: POST /api/system/restart or SIGTERM.
    Steps: drain flow tracker (2 s), XDP unload, flush CSV, tokio shutdown, re-exec.
    Files: core/ebpf/ (detach helpers), main.rs (signal handler + re-exec)

-- OPEN QUESTIONS -----------------------------------------

[ ] Dashboard attack/protocol counters never reset
    Accumulate for entire session lifetime; charts show historical totals.
    Consider: sliding window reset every N minutes, or cap at last 500 alerts.
    File: mantis-frontend/...dashboard.tsx
