AUTARCH v1.9 — remote monitoring, SSH manager, daemon, vault, cleanup
- Add Remote Monitoring Station with PIAP device profile system - Add SSH/SSHD manager with fail2ban integration - Add privileged daemon architecture for safe root operations - Add encrypted vault, HAL memory, HAL auto-analyst - Add network security suite, module creator, codex training - Add start.sh launcher script and GTK3 desktop launcher - Remove Output/ build artifacts, installer files, loose docs - Update .gitignore for runtime data and build artifacts - Update README for v1.9 with new launch method, screenshots, and features Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,89 +1,103 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Targets - AUTARCH{% endblock %}
|
||||
{% block title %}Investigations - AUTARCH{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header" style="display:flex;align-items:center;gap:1rem;flex-wrap:wrap">
|
||||
<div>
|
||||
<h1>Targets</h1>
|
||||
<h1>Investigations</h1>
|
||||
<p style="margin:0;font-size:0.85rem;color:var(--text-secondary)">
|
||||
Manage scope — IPs, CIDRs, domains, and URLs for your engagement.
|
||||
Investigation profiles for IPs, domains, threat actors, and incidents. Build detailed profiles with GeoIP, traceroute, DNS, WHOIS, and custom fields.
|
||||
</p>
|
||||
</div>
|
||||
<div style="margin-left:auto;display:flex;gap:0.5rem;flex-wrap:wrap">
|
||||
<button class="btn btn-sm btn-primary" onclick="toggleAddForm()">+ Add Target</button>
|
||||
<button class="btn btn-sm" onclick="exportTargets()">Export JSON</button>
|
||||
<label class="btn btn-sm" style="cursor:pointer" title="Import targets from JSON file">
|
||||
Import JSON
|
||||
<input type="file" accept=".json" style="display:none" onchange="importTargets(this)">
|
||||
</label>
|
||||
<button class="btn btn-sm btn-primary" onclick="toggleAddForm()">+ New Investigation</button>
|
||||
<button class="btn btn-sm" onclick="exportTargets()">Export</button>
|
||||
<label class="btn btn-sm" style="cursor:pointer">Import<input type="file" accept=".json" style="display:none" onchange="importTargets(this)"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Target Form -->
|
||||
<!-- Add Investigation Form -->
|
||||
<div id="add-form" class="section" style="display:none">
|
||||
<h2>Add Target</h2>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.75rem 1rem">
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-host">Host / IP / CIDR <span style="color:var(--danger)">*</span></label>
|
||||
<input type="text" id="add-host" placeholder="192.168.1.1 or example.com">
|
||||
<h2>New Investigation Profile</h2>
|
||||
|
||||
<!-- Basic Info -->
|
||||
<fieldset style="border:1px solid var(--border);border-radius:var(--radius);padding:0.75rem;margin-bottom:0.75rem">
|
||||
<legend style="font-size:0.85rem;font-weight:600;color:var(--accent);padding:0 0.5rem">Basic Info</legend>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.75rem">
|
||||
<div class="form-group" style="margin:0"><label>Host / IP <span style="color:var(--danger)">*</span></label><input type="text" id="add-host" placeholder="192.168.1.1 or example.com"></div>
|
||||
<div class="form-group" style="margin:0"><label>Name / Label</label><input type="text" id="add-name" placeholder="Investigation name"></div>
|
||||
<div class="form-group" style="margin:0"><label>Type</label><select id="add-type"><option value="ip">IP</option><option value="cidr">CIDR</option><option value="domain">Domain</option><option value="url">URL</option><option value="email">Email</option><option value="actor">Threat Actor</option><option value="incident">Incident</option></select></div>
|
||||
<div class="form-group" style="margin:0"><label>Status</label><select id="add-status"><option value="active">Active</option><option value="pending">Pending</option><option value="completed">Completed</option><option value="escalated">Escalated</option><option value="closed">Closed</option></select></div>
|
||||
<div class="form-group" style="margin:0"><label>Threat Level</label><select id="add-threat"><option value="unknown">Unknown</option><option value="low">Low</option><option value="medium">Medium</option><option value="high">High</option><option value="critical">Critical</option></select></div>
|
||||
<div class="form-group" style="margin:0"><label>OS</label><select id="add-os"><option>Unknown</option><option>Linux</option><option>Windows</option><option>macOS</option><option>Android</option><option>iOS</option><option>Network Device</option></select></div>
|
||||
<div class="form-group" style="margin:0"><label>Source</label><input type="text" id="add-source" placeholder="fail2ban, IDS, manual"></div>
|
||||
<div class="form-group" style="margin:0"><label>Tags</label><input type="text" id="add-tags" placeholder="brute-force, ssh, external"></div>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-name">Name / Label</label>
|
||||
<input type="text" id="add-name" placeholder="Corp Web Server">
|
||||
</fieldset>
|
||||
|
||||
<!-- Network Info -->
|
||||
<fieldset style="border:1px solid var(--border);border-radius:var(--radius);padding:0.75rem;margin-bottom:0.75rem">
|
||||
<legend style="font-size:0.85rem;font-weight:600;color:var(--accent);padding:0 0.5rem">Network</legend>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.75rem">
|
||||
<div class="form-group" style="margin:0"><label>IPv4</label><input type="text" id="add-ipv4" placeholder="192.168.1.1"></div>
|
||||
<div class="form-group" style="margin:0"><label>IPv6</label><input type="text" id="add-ipv6" placeholder="::1"></div>
|
||||
<div class="form-group" style="margin:0"><label>Domain</label><input type="text" id="add-domain" placeholder="example.com"></div>
|
||||
<div class="form-group" style="margin:0"><label>Reverse DNS</label><input type="text" id="add-rdns" placeholder="host.isp.net"></div>
|
||||
<div class="form-group" style="margin:0"><label>MAC Address</label><input type="text" id="add-mac" placeholder="aa:bb:cc:dd:ee:ff"></div>
|
||||
<div class="form-group" style="margin:0"><label>Hostname</label><input type="text" id="add-hostname" placeholder="server01"></div>
|
||||
<div class="form-group" style="margin:0"><label>Ports / Services</label><input type="text" id="add-ports" placeholder="22/ssh, 80/http, 443/https"></div>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-type">Type</label>
|
||||
<select id="add-type">
|
||||
<option value="ip">IP Address</option>
|
||||
<option value="cidr">CIDR / Range</option>
|
||||
<option value="domain">Domain</option>
|
||||
<option value="url">URL</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
|
||||
<!-- GeoIP -->
|
||||
<fieldset style="border:1px solid var(--border);border-radius:var(--radius);padding:0.75rem;margin-bottom:0.75rem">
|
||||
<legend style="font-size:0.85rem;font-weight:600;color:var(--accent);padding:0 0.5rem">GeoIP</legend>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.75rem">
|
||||
<div class="form-group" style="margin:0"><label>Country</label><input type="text" id="add-geo-country" placeholder="US"></div>
|
||||
<div class="form-group" style="margin:0"><label>City</label><input type="text" id="add-geo-city" placeholder="New York"></div>
|
||||
<div class="form-group" style="margin:0"><label>ISP</label><input type="text" id="add-geo-isp" placeholder="Comcast"></div>
|
||||
<div class="form-group" style="margin:0"><label>ASN</label><input type="text" id="add-geo-asn" placeholder="AS7922"></div>
|
||||
<div class="form-group" style="margin:0"><label>Coordinates</label><input type="text" id="add-geo-coords" placeholder="40.7128,-74.0060"></div>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-os">OS</label>
|
||||
<select id="add-os">
|
||||
<option>Unknown</option>
|
||||
<option>Linux</option>
|
||||
<option>Windows</option>
|
||||
<option>macOS</option>
|
||||
<option>Android</option>
|
||||
<option>iOS</option>
|
||||
<option>Network Device</option>
|
||||
<option>Other</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
|
||||
<!-- Intel -->
|
||||
<fieldset style="border:1px solid var(--border);border-radius:var(--radius);padding:0.75rem;margin-bottom:0.75rem">
|
||||
<legend style="font-size:0.85rem;font-weight:600;color:var(--accent);padding:0 0.5rem">Intelligence</legend>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:0.75rem">
|
||||
<div class="form-group" style="margin:0"><label>DNS Records</label><textarea id="add-dns" rows="2" placeholder="A: 1.2.3.4 MX: mail.example.com" style="font-family:monospace;font-size:0.78rem"></textarea></div>
|
||||
<div class="form-group" style="margin:0"><label>Email(s)</label><input type="text" id="add-email" placeholder="admin@example.com, abuse@isp.net"></div>
|
||||
<div class="form-group" style="margin:0"><label>Username(s)</label><input type="text" id="add-usernames" placeholder="root, admin, attacker123"></div>
|
||||
<div class="form-group" style="margin:0"><label>Vulnerabilities</label><textarea id="add-vulns" rows="2" placeholder="CVE-2024-1234, open SSH" style="font-family:monospace;font-size:0.78rem"></textarea></div>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-status">Status</label>
|
||||
<select id="add-status">
|
||||
<option value="active">Active</option>
|
||||
<option value="pending">Pending</option>
|
||||
<option value="completed">Completed</option>
|
||||
<option value="out-of-scope">Out of Scope</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-ports">Known Ports</label>
|
||||
<input type="text" id="add-ports" placeholder="22,80,443,8080">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:0.75rem 1rem;margin-top:0.75rem">
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-tags">Tags (comma-separated)</label>
|
||||
<input type="text" id="add-tags" placeholder="web, internal, critical">
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label for="add-notes">Notes</label>
|
||||
<input type="text" id="add-notes" placeholder="Brief notes about this target">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;gap:0.5rem;margin-top:1rem">
|
||||
<button class="btn btn-primary" onclick="addTarget()">Add Target</button>
|
||||
<div class="form-group" style="margin:0.5rem 0 0"><label>Traceroute</label><textarea id="add-traceroute" rows="3" placeholder="Paste traceroute output" style="font-family:monospace;font-size:0.78rem;width:100%"></textarea></div>
|
||||
<div class="form-group" style="margin:0.5rem 0 0"><label>WHOIS</label><textarea id="add-whois" rows="3" placeholder="Paste WHOIS output" style="font-family:monospace;font-size:0.78rem;width:100%"></textarea></div>
|
||||
<div class="form-group" style="margin:0.5rem 0 0"><label>Notes</label><textarea id="add-notes" rows="3" placeholder="Investigation notes, observations, timeline..." style="font-size:0.82rem;width:100%"></textarea></div>
|
||||
</fieldset>
|
||||
|
||||
<!-- Custom Fields -->
|
||||
<fieldset style="border:1px solid var(--border);border-radius:var(--radius);padding:0.75rem;margin-bottom:0.75rem">
|
||||
<legend style="font-size:0.85rem;font-weight:600;color:var(--accent);padding:0 0.5rem">Custom Fields</legend>
|
||||
<div id="custom-fields-container"></div>
|
||||
<button class="btn btn-sm" onclick="addCustomField()" style="margin-top:0.5rem">+ Add Field</button>
|
||||
</fieldset>
|
||||
|
||||
<div style="display:flex;gap:0.5rem;margin-top:0.75rem">
|
||||
<button class="btn btn-primary" onclick="addTarget()">Create Investigation</button>
|
||||
<button class="btn btn-sm" onclick="toggleAddForm()">Cancel</button>
|
||||
<span id="add-status-msg" style="font-size:0.82rem;color:var(--text-secondary);align-self:center"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Investigation Reports -->
|
||||
<div class="section">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.75rem">
|
||||
<h2 style="margin:0">Investigation Reports</h2>
|
||||
<button class="btn btn-sm" onclick="loadIRs()">Refresh</button>
|
||||
</div>
|
||||
<div id="ir-list" style="margin-bottom:0.5rem"><p style="color:var(--text-muted)">Loading reports...</p></div>
|
||||
</div>
|
||||
|
||||
<!-- Filter / Search -->
|
||||
<div class="section" style="padding:0.6rem 1rem">
|
||||
<div style="display:flex;gap:0.75rem;align-items:center;flex-wrap:wrap">
|
||||
@@ -272,24 +286,74 @@ function toggleAddForm() {
|
||||
}
|
||||
|
||||
// ── Add target ────────────────────────────────────────────────────────────────
|
||||
var _customFieldCount = 0;
|
||||
function addCustomField() {
|
||||
_customFieldCount++;
|
||||
var container = document.getElementById('custom-fields-container');
|
||||
var row = document.createElement('div');
|
||||
row.style.cssText = 'display:flex;gap:0.5rem;align-items:flex-start;margin-bottom:0.5rem;flex-wrap:wrap';
|
||||
row.innerHTML = '<input type="text" class="cf-name" placeholder="Field name" style="width:150px;padding:0.3rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-input);color:inherit;font-size:0.8rem">'
|
||||
+ '<select class="cf-type" style="width:130px;padding:0.3rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-input);color:inherit;font-size:0.8rem">'
|
||||
+ '<option value="text">Text</option><option value="ipv4">IPv4</option><option value="ipv6">IPv6</option>'
|
||||
+ '<option value="domain">Domain</option><option value="dns">DNS Record</option>'
|
||||
+ '<option value="email">Email</option><option value="username">Username</option>'
|
||||
+ '<option value="url">URL</option><option value="mac">MAC Address</option>'
|
||||
+ '<option value="hash">Hash</option><option value="misc">Misc (4000 char)</option></select>'
|
||||
+ '<input type="text" class="cf-value" placeholder="Value" style="flex:1;min-width:200px;padding:0.3rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-input);color:inherit;font-size:0.8rem">'
|
||||
+ '<button class="btn btn-sm" onclick="this.parentElement.remove()" style="padding:2px 8px;color:var(--danger)">X</button>';
|
||||
container.appendChild(row);
|
||||
}
|
||||
|
||||
function _getVal(id) { var e = document.getElementById(id); return e ? (e.value||'').trim() : ''; }
|
||||
|
||||
function addTarget() {
|
||||
var host = document.getElementById('add-host').value.trim();
|
||||
var host = _getVal('add-host');
|
||||
if (!host) { document.getElementById('add-host').focus(); return; }
|
||||
var msg = document.getElementById('add-status-msg');
|
||||
msg.textContent = 'Saving…';
|
||||
|
||||
// Collect custom fields
|
||||
var customFields = [];
|
||||
document.querySelectorAll('#custom-fields-container > div').forEach(function(row) {
|
||||
var name = row.querySelector('.cf-name').value.trim();
|
||||
var type = row.querySelector('.cf-type').value;
|
||||
var value = row.querySelector('.cf-value').value.trim();
|
||||
if (name && value) customFields.push({name: name, type: type, value: value});
|
||||
});
|
||||
|
||||
fetch('/targets/add', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
host: host,
|
||||
name: document.getElementById('add-name').value,
|
||||
type: document.getElementById('add-type').value,
|
||||
os: document.getElementById('add-os').value,
|
||||
status: document.getElementById('add-status').value,
|
||||
ports: document.getElementById('add-ports').value,
|
||||
tags: document.getElementById('add-tags').value,
|
||||
notes: document.getElementById('add-notes').value,
|
||||
host: host,
|
||||
name: _getVal('add-name'),
|
||||
type: _getVal('add-type'),
|
||||
os: _getVal('add-os'),
|
||||
status: _getVal('add-status'),
|
||||
threat_level: _getVal('add-threat'),
|
||||
source: _getVal('add-source'),
|
||||
ports: _getVal('add-ports'),
|
||||
tags: _getVal('add-tags'),
|
||||
notes: _getVal('add-notes'),
|
||||
ipv4: _getVal('add-ipv4'),
|
||||
ipv6: _getVal('add-ipv6'),
|
||||
domain: _getVal('add-domain'),
|
||||
rdns: _getVal('add-rdns'),
|
||||
mac_address: _getVal('add-mac'),
|
||||
hostname: _getVal('add-hostname'),
|
||||
services: _getVal('add-ports'),
|
||||
geo_country: _getVal('add-geo-country'),
|
||||
geo_city: _getVal('add-geo-city'),
|
||||
geo_isp: _getVal('add-geo-isp'),
|
||||
geo_asn: _getVal('add-geo-asn'),
|
||||
geo_coords: _getVal('add-geo-coords'),
|
||||
dns_records: _getVal('add-dns'),
|
||||
email: _getVal('add-email'),
|
||||
usernames: _getVal('add-usernames'),
|
||||
vulns: _getVal('add-vulns'),
|
||||
traceroute: _getVal('add-traceroute'),
|
||||
whois: _getVal('add-whois'),
|
||||
custom_fields: customFields,
|
||||
})
|
||||
}).then(function(r){ return r.json(); })
|
||||
.then(function(d) {
|
||||
@@ -434,6 +498,90 @@ document.addEventListener('DOMContentLoaded', function(){
|
||||
document.getElementById('add-notes').addEventListener('keypress', function(e){
|
||||
if (e.key === 'Enter') addTarget();
|
||||
});
|
||||
loadIRs();
|
||||
});
|
||||
|
||||
function loadIRs() {
|
||||
fetch('/targets/ir').then(function(r){ return r.json(); }).then(function(d) {
|
||||
var el = document.getElementById('ir-list');
|
||||
if (!d.ok || !d.reports || !d.reports.length) {
|
||||
el.innerHTML = '<p style="color:var(--text-muted);font-size:0.85rem">No investigation reports yet. Use HAL\'s "Report Only" or "Let HAL Fix It + IR" buttons after a scan.</p>';
|
||||
return;
|
||||
}
|
||||
var html = '<table class="data-table" style="font-size:0.82rem;width:100%"><thead><tr>'
|
||||
+ '<th>ID</th><th>Title</th><th>Risk</th><th>Status</th><th>Source</th><th>Created</th><th>Actions</th>'
|
||||
+ '</tr></thead><tbody>';
|
||||
d.reports.forEach(function(r) {
|
||||
var riskColors = {critical:'#ff3b30',high:'#ff6b35',medium:'#f59e0b',low:'#8ec07c',clean:'#34c759',unknown:'#888'};
|
||||
var rc = riskColors[r.risk_level] || '#888';
|
||||
var halBadge = r.created_by_hal ? ' <span style="background:var(--accent);color:#000;font-size:0.6rem;padding:1px 4px;border-radius:2px;font-weight:700">HAL</span>' : '';
|
||||
var statusColor = r.status === 'closed' ? 'var(--text-muted)' : r.status === 'open' ? 'var(--accent)' : '#f59e0b';
|
||||
var created = r.created_at ? new Date(r.created_at).toLocaleString() : '';
|
||||
html += '<tr>'
|
||||
+ '<td><strong style="font-family:monospace;color:var(--accent)">' + escapeHtml(r.id) + '</strong>' + halBadge + '</td>'
|
||||
+ '<td>' + escapeHtml(r.title || '') + '</td>'
|
||||
+ '<td><span style="color:' + rc + ';font-weight:600;text-transform:uppercase;font-size:0.75rem">' + escapeHtml(r.risk_level || 'unknown') + '</span></td>'
|
||||
+ '<td><span style="color:' + statusColor + '">' + escapeHtml(r.status || '') + '</span></td>'
|
||||
+ '<td style="font-size:0.75rem">' + escapeHtml(r.source || '') + '</td>'
|
||||
+ '<td style="font-size:0.75rem">' + escapeHtml(created) + '</td>'
|
||||
+ '<td style="white-space:nowrap">'
|
||||
+ '<button class="btn btn-sm" style="font-size:0.65rem;padding:1px 6px;margin-right:3px" onclick="viewIR(\'' + escapeHtml(r.id) + '\')">View</button>'
|
||||
+ '<button class="btn btn-sm" style="font-size:0.65rem;padding:1px 6px;margin-right:3px" onclick="loadIRToHal(\'' + escapeHtml(r.id) + '\')">Send to HAL</button>'
|
||||
+ '<button class="btn btn-sm" style="font-size:0.65rem;padding:1px 6px;color:var(--danger);border-color:var(--danger)" onclick="deleteIR(\'' + escapeHtml(r.id) + '\')">Delete</button>'
|
||||
+ '</td></tr>';
|
||||
});
|
||||
html += '</tbody></table>';
|
||||
el.innerHTML = html;
|
||||
}).catch(function() {
|
||||
document.getElementById('ir-list').innerHTML = '<p style="color:var(--danger)">Failed to load reports.</p>';
|
||||
});
|
||||
}
|
||||
|
||||
function viewIR(irId) {
|
||||
fetch('/targets/ir/' + irId).then(function(r){ return r.json(); }).then(function(d) {
|
||||
if (!d.ok) { alert('IR not found'); return; }
|
||||
var ir = d.ir;
|
||||
var w = window.open('', '_blank', 'width=700,height=600');
|
||||
w.document.write('<html><head><title>' + ir.id + '</title>'
|
||||
+ '<style>body{background:#1a1a2e;color:#e0e0e0;font-family:system-ui;padding:20px;font-size:14px} '
|
||||
+ 'h1{color:#00ff41;font-size:1.2rem} h2{color:#5ac8fa;font-size:1rem;margin-top:1rem} '
|
||||
+ 'pre{background:#12122a;padding:10px;border-radius:6px;white-space:pre-wrap;font-size:0.82rem;border:1px solid #333} '
|
||||
+ '.badge{display:inline-block;padding:2px 8px;border-radius:3px;font-size:0.75rem;font-weight:700}</style></head><body>');
|
||||
w.document.write('<h1>' + ir.id + (ir.created_by_hal ? ' <span class="badge" style="background:#00ff41;color:#000">HAL</span>' : '') + '</h1>');
|
||||
w.document.write('<div><strong>Title:</strong> ' + (ir.title||'') + '</div>');
|
||||
w.document.write('<div><strong>Status:</strong> ' + (ir.status||'') + ' · <strong>Risk:</strong> ' + (ir.risk_level||'') + ' · <strong>Source:</strong> ' + (ir.source||'') + '</div>');
|
||||
w.document.write('<div><strong>Created:</strong> ' + (ir.created_at||'') + '</div>');
|
||||
if (ir.ip) w.document.write('<div><strong>IP:</strong> ' + ir.ip + '</div>');
|
||||
if (ir.analysis) { w.document.write('<h2>Analysis</h2><pre>' + ir.analysis.replace(/</g,'<') + '</pre>'); }
|
||||
if (ir.fix_attempted) {
|
||||
w.document.write('<h2>Fix Attempted</h2><pre>' + (ir.fix_results||'').replace(/</g,'<') + '</pre>');
|
||||
}
|
||||
if (ir.notes) { w.document.write('<h2>Notes</h2><pre>' + ir.notes.replace(/</g,'<') + '</pre>'); }
|
||||
w.document.write('</body></html>');
|
||||
w.document.close();
|
||||
});
|
||||
}
|
||||
|
||||
function loadIRToHal(irId) {
|
||||
fetch('/targets/ir/' + irId + '/load-to-hal', {method:'POST'}).then(function(r){return r.json()}).then(function(d) {
|
||||
if (d.ok) {
|
||||
// Open HAL panel and show the loaded IR
|
||||
var panel = document.getElementById('hal-panel');
|
||||
if (panel) panel.style.display = 'flex';
|
||||
halAppendStyled('status', 'Loaded IR ' + d.ir.id + ' into HAL memory');
|
||||
halAppendStyled('bot', 'IR ' + d.ir.id + ': ' + (d.ir.title||'') + '\nRisk: ' + (d.ir.risk_level||'unknown') + '\nStatus: ' + (d.ir.status||'') + '\n\nAnalysis loaded. Ask me to continue working on this investigation.');
|
||||
halScroll();
|
||||
} else {
|
||||
alert('Failed to load IR: ' + (d.error||''));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteIR(irId) {
|
||||
if (!confirm('Delete investigation report ' + irId + '?')) return;
|
||||
fetch('/targets/ir/' + irId + '/delete', {method:'POST'}).then(function(r){return r.json()}).then(function(d) {
|
||||
loadIRs();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user