@@ -2199,6 +2207,169 @@
border-radius: 4px;
margin-top: 8px;
}
+ /* TSCM Device Details Modal */
+ .tscm-modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.8);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 10000;
+ }
+ .tscm-modal {
+ background: var(--panel-bg);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ max-width: 500px;
+ width: 90%;
+ max-height: 80vh;
+ overflow-y: auto;
+ position: relative;
+ }
+ .tscm-modal-close {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ background: none;
+ border: none;
+ color: var(--text-muted);
+ font-size: 24px;
+ cursor: pointer;
+ z-index: 1;
+ }
+ .tscm-modal-close:hover { color: #fff; }
+ .device-detail-header {
+ padding: 16px;
+ border-bottom: 1px solid var(--border-color);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+ .device-detail-header h3 {
+ margin: 0;
+ font-size: 16px;
+ }
+ .device-detail-header.classification-red { background: rgba(255, 51, 51, 0.15); }
+ .device-detail-header.classification-yellow { background: rgba(255, 204, 0, 0.15); }
+ .device-detail-header.classification-green { background: rgba(0, 204, 0, 0.15); }
+ .device-detail-protocol {
+ font-size: 10px;
+ padding: 3px 8px;
+ background: rgba(255, 255, 255, 0.1);
+ border-radius: 3px;
+ text-transform: uppercase;
+ }
+ .device-detail-score {
+ display: flex;
+ align-items: center;
+ padding: 16px;
+ gap: 16px;
+ border-bottom: 1px solid var(--border-color);
+ }
+ .score-circle {
+ width: 70px;
+ height: 70px;
+ border-radius: 50%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ border: 3px solid;
+ }
+ .score-circle.high { border-color: #ff3333; background: rgba(255, 51, 51, 0.1); }
+ .score-circle.medium { border-color: #ffcc00; background: rgba(255, 204, 0, 0.1); }
+ .score-circle.low { border-color: #00cc00; background: rgba(0, 204, 0, 0.1); }
+ .score-circle .score-value {
+ font-size: 24px;
+ font-weight: 700;
+ }
+ .score-circle.high .score-value { color: #ff3333; }
+ .score-circle.medium .score-value { color: #ffcc00; }
+ .score-circle.low .score-value { color: #00cc00; }
+ .score-circle .score-label {
+ font-size: 8px;
+ color: var(--text-muted);
+ text-transform: uppercase;
+ }
+ .score-breakdown {
+ flex: 1;
+ font-size: 12px;
+ line-height: 1.6;
+ }
+ .device-detail-section {
+ padding: 16px;
+ border-bottom: 1px solid var(--border-color);
+ }
+ .device-detail-section h4 {
+ margin: 0 0 12px 0;
+ font-size: 12px;
+ color: var(--text-muted);
+ text-transform: uppercase;
+ }
+ .device-detail-table {
+ width: 100%;
+ font-size: 12px;
+ }
+ .device-detail-table td {
+ padding: 4px 0;
+ }
+ .device-detail-table td:first-child {
+ color: var(--text-muted);
+ width: 40%;
+ }
+ .indicator-list {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+ .indicator-item {
+ display: flex;
+ gap: 10px;
+ padding: 8px;
+ background: rgba(0, 0, 0, 0.2);
+ border-radius: 4px;
+ font-size: 11px;
+ }
+ .indicator-type {
+ background: rgba(255, 153, 51, 0.2);
+ color: #ff9933;
+ padding: 2px 6px;
+ border-radius: 3px;
+ font-size: 10px;
+ white-space: nowrap;
+ }
+ .indicator-desc {
+ color: var(--text-color);
+ }
+ .device-reasons-list {
+ margin: 0;
+ padding-left: 20px;
+ font-size: 12px;
+ }
+ .device-reasons-list li {
+ margin-bottom: 4px;
+ }
+ .device-detail-disclaimer {
+ padding: 12px 16px;
+ font-size: 10px;
+ color: var(--text-muted);
+ background: rgba(74, 158, 255, 0.1);
+ border-top: 1px solid rgba(74, 158, 255, 0.3);
+ }
+ .tscm-threat-action {
+ margin-top: 6px;
+ font-size: 10px;
+ color: #ff9933;
+ text-transform: uppercase;
+ font-weight: 600;
+ }
+ .tscm-device-item {
+ cursor: pointer;
+ }
.tscm-threat-list {
display: flex;
flex-direction: column;
@@ -10066,6 +10237,11 @@
if (!exists) {
tscmWifiDevices.push(device);
updateTscmDisplays();
+ updateTscmThreatCounts();
+ // Add to high interest if score >= 6
+ if (device.score >= 6) {
+ addHighInterestDevice(device, 'wifi');
+ }
}
}
@@ -10075,6 +10251,11 @@
if (!exists) {
tscmBtDevices.push(device);
updateTscmDisplays();
+ updateTscmThreatCounts();
+ // Add to high interest if score >= 6
+ if (device.score >= 6) {
+ addHighInterestDevice(device, 'bluetooth');
+ }
}
}
@@ -10085,6 +10266,52 @@
if (!exists) {
tscmRfSignals.push(signal);
updateTscmDisplays();
+ updateTscmThreatCounts();
+ // Add to high interest if score >= 6
+ if (signal.score >= 6) {
+ addHighInterestDevice(signal, 'rf');
+ }
+ }
+ }
+
+ // Track high-interest devices for the threats panel
+ let tscmHighInterestDevices = [];
+ function addHighInterestDevice(device, protocol) {
+ const id = device.mac || device.bssid || device.frequency;
+ const exists = tscmHighInterestDevices.some(d => d.id === id);
+ if (!exists) {
+ tscmHighInterestDevices.push({
+ id: id,
+ protocol: protocol,
+ name: device.name || device.ssid || `${device.frequency} MHz`,
+ score: device.score,
+ classification: device.classification,
+ indicators: device.indicators || [],
+ recommended_action: device.recommended_action,
+ device: device
+ });
+ updateHighInterestPanel();
+ }
+ }
+
+ function updateHighInterestPanel() {
+ const panel = document.getElementById('tscmThreatList');
+ if (tscmHighInterestDevices.length === 0) {
+ panel.innerHTML = '
No high-interest devices detected
';
+ } else {
+ panel.innerHTML = '
' + tscmHighInterestDevices.map(d => `
+
+
+
+ ${escapeHtml(d.name)}
+ ${d.indicators.slice(0, 2).map(i => i.desc || i.type).join(' | ')}
+
+
${d.recommended_action || 'investigate'}
+
+ `).join('') + '
';
}
}
@@ -10193,6 +10420,123 @@
return `
Score: ${score}`;
}
+ // Store all devices for lookup
+ function getAllTscmDevices() {
+ const devices = {};
+ tscmWifiDevices.forEach(d => { devices[`wifi:${d.bssid}`] = {...d, protocol: 'wifi'}; });
+ tscmBtDevices.forEach(d => { devices[`bluetooth:${d.mac}`] = {...d, protocol: 'bluetooth'}; });
+ tscmRfSignals.forEach(d => { devices[`rf:${d.frequency}`] = {...d, protocol: 'rf'}; });
+ return devices;
+ }
+
+ function showDeviceDetails(id, protocol) {
+ const devices = getAllTscmDevices();
+ const key = `${protocol}:${id}`;
+ const device = devices[key];
+
+ if (!device) {
+ console.warn('Device not found:', key);
+ return;
+ }
+
+ const modal = document.getElementById('tscmDeviceModal');
+ const content = document.getElementById('tscmDeviceModalContent');
+
+ // Build detailed view
+ let html = `
+
+
+
+
+ ${device.score || 0}
+ SCORE
+
+
+ Risk Level: ${device.classification === 'high_interest' ? 'HIGH INTEREST' : device.classification === 'review' ? 'NEEDS REVIEW' : 'INFORMATIONAL'}
+ Recommended Action: ${device.recommended_action || 'Monitor'}
+
+
+
+
+
Device Information
+
+ `;
+
+ // Add device-specific fields
+ if (protocol === 'wifi') {
+ html += `
+ | BSSID | ${device.bssid || 'Unknown'} |
+ | SSID | ${escapeHtml(device.ssid || '[Hidden]')} |
+ | Channel | ${device.channel || 'Unknown'} |
+ | Signal | ${device.signal || '--'} dBm |
+ | Security | ${device.security || 'Unknown'} |
+ `;
+ } else if (protocol === 'bluetooth') {
+ html += `
+ | MAC Address | ${device.mac || 'Unknown'} |
+ | Name | ${escapeHtml(device.name || 'Unknown')} |
+ | Type | ${device.device_type || 'Unknown'} |
+ | RSSI | ${device.rssi || '--'} dBm |
+ | Audio Capable | ${device.is_audio_capable ? 'Yes' : 'No'} |
+ `;
+ } else if (protocol === 'rf') {
+ html += `
+ | Frequency | ${device.frequency?.toFixed(3) || 'Unknown'} MHz |
+ | Band | ${device.band || 'Unknown'} |
+ | Power | ${device.power?.toFixed(1) || '--'} dBm |
+ | Signal Strength | +${(device.signal_strength || 0).toFixed(1)} dB above noise |
+ `;
+ }
+ html += `
`;
+
+ // Add indicators section
+ if (device.indicators && device.indicators.length > 0) {
+ html += `
+
+
Risk Indicators (Why This Score)
+
+ ${device.indicators.map(i => `
+
+ ${i.type}
+ ${escapeHtml(i.desc || '')}
+
+ `).join('')}
+
+
+ `;
+ }
+
+ // Add reasons section
+ if (device.reasons && device.reasons.length > 0) {
+ html += `
+
+
Detection Notes
+
+ ${device.reasons.map(r => `- ${escapeHtml(r)}
`).join('')}
+
+
+ `;
+ }
+
+ // Add disclaimer
+ html += `
+
+ Disclaimer: This analysis identifies indicators and anomalies.
+ It does NOT confirm surveillance activity. Professional verification required.
+
+ `;
+
+ content.innerHTML = html;
+ modal.style.display = 'flex';
+ }
+
+ function closeTscmDeviceModal() {
+ document.getElementById('tscmDeviceModal').style.display = 'none';
+ }
+
function updateTscmDisplays() {
// Update WiFi list
const wifiList = document.getElementById('tscmWifiList');
@@ -10202,7 +10546,7 @@
// Sort by score (highest first)
const sorted = [...tscmWifiDevices].sort((a, b) => (b.score || 0) - (a.score || 0));
wifiList.innerHTML = sorted.map(d => `
-