Phase 5: Final integration — fix imports, full module discovery, interactive menu

- Fix pyserial import error in cellular_backup.py (lazy import with fallback)
- Replace stealth-only module discovery with discover_all_modules() across all
  5 categories (stealth, passive, active, intel, connectivity)
- Wire up interactive menu options 5-8:
  - View Credentials: query credential_db SQLite, Rich table with stats
  - View Intelligence: host count, cred stats, security posture summary
  - Network Topology: host table from topology_mapper state data
  - Timeline: recent entries from operator_audit HMAC-chained log
- Update start command to discover+register all enabled modules (not just stealth)
- Update modules/activate/selftest commands to use full module discovery
- Add is_module_enabled() config-aware helper for per-category defaults
- Fix modules.yaml module count headers (16->17 passive, 8->9 active/intel)
- Set bettercap_mgr enabled=false (all active modules disabled by default)
- Add tests/test_all_modules.py: 179 parametrized tests covering import,
  BaseModule subclass, attributes, and instantiation for all 55 modules
  across passive, active, intel, and connectivity categories
- All 256 tests passing
This commit is contained in:
n0mad1k
2026-03-18 13:59:27 -04:00
parent ba5143b560
commit 56cca8ac3d
4 changed files with 847 additions and 40 deletions
+11 -1
View File
@@ -11,11 +11,15 @@ OPi Zero 3+ only — skips on pi_zero tier (no USB bandwidth for modem).
import logging
import os
import re
import serial
import subprocess
import time
from typing import Optional
try:
import serial
except ImportError:
serial = None
from modules.base import BaseModule
logger = logging.getLogger("bb.connectivity.cellular_backup")
@@ -51,6 +55,12 @@ class CellularBackup(BaseModule):
if self._running:
return
if serial is None:
logger.error("pyserial not installed — cellular backup unavailable")
self.state.set_module_status(self.name, "error",
extra={"reason": "pyserial_missing"})
return
# Check hardware tier
device_tier = self.config.get("device", {}).get("tier", "")
if device_tier == "pi_zero":