mirror of
https://github.com/smittix/intercept.git
synced 2026-07-05 16:18:12 -07:00
feat: add category filter to TSCM report exports
Users can now choose which risk categories to include in generated reports — High Interest, Needs Review, and Informational — via three checkboxes that appear after a sweep completes. Applies to the HTML report, PDF, JSON annex, and CSV annex. Defaults to High Interest + Needs Review (Informational excluded) to keep reports concise. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+71
-59
@@ -95,14 +95,14 @@ class TSCMReport:
|
||||
# Meeting window summaries
|
||||
meeting_summaries: list[ReportMeetingSummary] = field(default_factory=list)
|
||||
|
||||
# Statistics
|
||||
total_devices_scanned: int = 0
|
||||
wifi_devices: int = 0
|
||||
wifi_clients: int = 0
|
||||
bluetooth_devices: int = 0
|
||||
rf_signals: int = 0
|
||||
new_devices: int = 0
|
||||
missing_devices: int = 0
|
||||
# Statistics
|
||||
total_devices_scanned: int = 0
|
||||
wifi_devices: int = 0
|
||||
wifi_clients: int = 0
|
||||
bluetooth_devices: int = 0
|
||||
rf_signals: int = 0
|
||||
new_devices: int = 0
|
||||
missing_devices: int = 0
|
||||
|
||||
# Sweep duration
|
||||
sweep_start: datetime | None = None
|
||||
@@ -194,13 +194,13 @@ def generate_executive_summary(report: TSCMReport) -> str:
|
||||
lines.append("")
|
||||
|
||||
# Key statistics
|
||||
lines.append("SCAN STATISTICS:")
|
||||
lines.append(f" - Total devices scanned: {report.total_devices_scanned}")
|
||||
lines.append(f" - WiFi access points: {report.wifi_devices}")
|
||||
lines.append(f" - WiFi clients: {report.wifi_clients}")
|
||||
lines.append(f" - Bluetooth devices: {report.bluetooth_devices}")
|
||||
lines.append(f" - RF signals: {report.rf_signals}")
|
||||
lines.append("")
|
||||
lines.append("SCAN STATISTICS:")
|
||||
lines.append(f" - Total devices scanned: {report.total_devices_scanned}")
|
||||
lines.append(f" - WiFi access points: {report.wifi_devices}")
|
||||
lines.append(f" - WiFi clients: {report.wifi_clients}")
|
||||
lines.append(f" - Bluetooth devices: {report.bluetooth_devices}")
|
||||
lines.append(f" - RF signals: {report.rf_signals}")
|
||||
lines.append("")
|
||||
|
||||
# Findings summary
|
||||
lines.append("FINDINGS SUMMARY:")
|
||||
@@ -422,14 +422,14 @@ def generate_technical_annex_json(report: TSCMReport) -> dict:
|
||||
'capabilities': report.capabilities,
|
||||
'limitations': report.limitations,
|
||||
|
||||
'statistics': {
|
||||
'total_devices': report.total_devices_scanned,
|
||||
'wifi_devices': report.wifi_devices,
|
||||
'wifi_clients': report.wifi_clients,
|
||||
'bluetooth_devices': report.bluetooth_devices,
|
||||
'rf_signals': report.rf_signals,
|
||||
'new_devices': report.new_devices,
|
||||
'missing_devices': report.missing_devices,
|
||||
'statistics': {
|
||||
'total_devices': report.total_devices_scanned,
|
||||
'wifi_devices': report.wifi_devices,
|
||||
'wifi_clients': report.wifi_clients,
|
||||
'bluetooth_devices': report.bluetooth_devices,
|
||||
'rf_signals': report.rf_signals,
|
||||
'new_devices': report.new_devices,
|
||||
'missing_devices': report.missing_devices,
|
||||
'high_interest_count': len(report.high_interest_findings),
|
||||
'needs_review_count': len(report.needs_review_findings),
|
||||
'informational_count': len(report.informational_findings),
|
||||
@@ -776,23 +776,23 @@ class TSCMReportBuilder:
|
||||
self.report.meeting_summaries.append(meeting)
|
||||
return self
|
||||
|
||||
def add_statistics(
|
||||
self,
|
||||
wifi: int = 0,
|
||||
wifi_clients: int = 0,
|
||||
bluetooth: int = 0,
|
||||
rf: int = 0,
|
||||
new: int = 0,
|
||||
missing: int = 0
|
||||
) -> TSCMReportBuilder:
|
||||
self.report.wifi_devices = wifi
|
||||
self.report.wifi_clients = wifi_clients
|
||||
self.report.bluetooth_devices = bluetooth
|
||||
self.report.rf_signals = rf
|
||||
self.report.total_devices_scanned = wifi + wifi_clients + bluetooth + rf
|
||||
self.report.new_devices = new
|
||||
self.report.missing_devices = missing
|
||||
return self
|
||||
def add_statistics(
|
||||
self,
|
||||
wifi: int = 0,
|
||||
wifi_clients: int = 0,
|
||||
bluetooth: int = 0,
|
||||
rf: int = 0,
|
||||
new: int = 0,
|
||||
missing: int = 0
|
||||
) -> TSCMReportBuilder:
|
||||
self.report.wifi_devices = wifi
|
||||
self.report.wifi_clients = wifi_clients
|
||||
self.report.bluetooth_devices = bluetooth
|
||||
self.report.rf_signals = rf
|
||||
self.report.total_devices_scanned = wifi + wifi_clients + bluetooth + rf
|
||||
self.report.new_devices = new
|
||||
self.report.missing_devices = missing
|
||||
return self
|
||||
|
||||
def add_device_timelines(self, timelines: list[dict]) -> TSCMReportBuilder:
|
||||
self.report.device_timelines = timelines
|
||||
@@ -847,6 +847,7 @@ def generate_report(
|
||||
baseline_diff: dict | None = None,
|
||||
meeting_summaries: list[dict] | None = None,
|
||||
correlations: list[dict] | None = None,
|
||||
categories: list[str] | None = None,
|
||||
) -> TSCMReport:
|
||||
"""
|
||||
Generate a complete TSCM report from sweep data.
|
||||
@@ -882,34 +883,45 @@ def generate_report(
|
||||
# Capabilities
|
||||
builder.add_capabilities(capabilities)
|
||||
|
||||
# Apply category filter before building findings
|
||||
if categories:
|
||||
_cat_map = {'needs_review': {'review', 'needs_review'}}
|
||||
allowed = set()
|
||||
for c in categories:
|
||||
allowed |= _cat_map.get(c, {c})
|
||||
device_profiles = [
|
||||
p for p in device_profiles
|
||||
if p.get('risk_level', 'informational') in allowed
|
||||
]
|
||||
|
||||
# Add findings from profiles
|
||||
builder.add_findings_from_profiles(device_profiles)
|
||||
|
||||
# Statistics
|
||||
results = sweep_data.get('results', {})
|
||||
wifi_count = results.get('wifi_count')
|
||||
if wifi_count is None:
|
||||
wifi_count = len(results.get('wifi_devices', results.get('wifi', [])))
|
||||
|
||||
wifi_client_count = results.get('wifi_client_count')
|
||||
if wifi_client_count is None:
|
||||
wifi_client_count = len(results.get('wifi_clients', []))
|
||||
|
||||
bt_count = results.get('bt_count')
|
||||
if bt_count is None:
|
||||
bt_count = len(results.get('bt_devices', results.get('bluetooth', [])))
|
||||
results = sweep_data.get('results', {})
|
||||
wifi_count = results.get('wifi_count')
|
||||
if wifi_count is None:
|
||||
wifi_count = len(results.get('wifi_devices', results.get('wifi', [])))
|
||||
|
||||
wifi_client_count = results.get('wifi_client_count')
|
||||
if wifi_client_count is None:
|
||||
wifi_client_count = len(results.get('wifi_clients', []))
|
||||
|
||||
bt_count = results.get('bt_count')
|
||||
if bt_count is None:
|
||||
bt_count = len(results.get('bt_devices', results.get('bluetooth', [])))
|
||||
|
||||
rf_count = results.get('rf_count')
|
||||
if rf_count is None:
|
||||
rf_count = len(results.get('rf_signals', results.get('rf', [])))
|
||||
|
||||
builder.add_statistics(
|
||||
wifi=wifi_count,
|
||||
wifi_clients=wifi_client_count,
|
||||
bluetooth=bt_count,
|
||||
rf=rf_count,
|
||||
new=baseline_diff.get('summary', {}).get('new_devices', 0) if baseline_diff else 0,
|
||||
missing=baseline_diff.get('summary', {}).get('missing_devices', 0) if baseline_diff else 0,
|
||||
builder.add_statistics(
|
||||
wifi=wifi_count,
|
||||
wifi_clients=wifi_client_count,
|
||||
bluetooth=bt_count,
|
||||
rf=rf_count,
|
||||
new=baseline_diff.get('summary', {}).get('new_devices', 0) if baseline_diff else 0,
|
||||
missing=baseline_diff.get('summary', {}).get('missing_devices', 0) if baseline_diff else 0,
|
||||
)
|
||||
|
||||
# Technical data
|
||||
|
||||
Reference in New Issue
Block a user