diff --git a/api/wevia-cyber-archi-control.php b/api/wevia-cyber-archi-control.php new file mode 100644 index 000000000..42ece5459 --- /dev/null +++ b/api/wevia-cyber-archi-control.php @@ -0,0 +1,160 @@ +&1 | head -40"); + return ['provider' => 'wevia-cyber', 'content' => "NMAP PORTSCAN $mt[2]:\n$out", 'tool' => 'cyber_portscan']; + } + + // CYBER-2: cyber_ssl_check + if (preg_match('/\b(ssl\s+check|testssl|ssl\s+audit|tls\s+check)\s+(\S+)/', $m, $mt)) { + $target = escapeshellarg($mt[2]); + $out = @shell_exec("sudo /usr/local/bin/testssl.sh --fast --quiet --color 0 $target 2>&1 | head -30"); + if (!$out) $out = @shell_exec("echo | openssl s_client -connect $mt[2]:443 2>&1 | openssl x509 -noout -dates -subject -issuer 2>&1"); + return ['provider' => 'wevia-cyber', 'content' => "SSL/TLS AUDIT $mt[2]:\n" . ($out ?: 'no output'), 'tool' => 'cyber_ssl_check']; + } + + // CYBER-3: cyber_web_scan (nikto) + if (preg_match('/\b(nikto|web\s+scan|web\s+vuln)\s+(https?:\/\/\S+)/', $m, $mt)) { + $target = escapeshellarg($mt[2]); + $out = @shell_exec("sudo nikto -h $target -maxtime 30s 2>&1 | head -30"); + return ['provider' => 'wevia-cyber', 'content' => "NIKTO WEB SCAN $mt[2]:\n$out", 'tool' => 'cyber_web_scan']; + } + + // CYBER-4: cyber_full_audit (own infra only) + if (preg_match('/\b(cyber\s+audit|security\s+audit|audit\s+securite)\s+(infra|s204|s95|s151|weval)/', $m, $mt)) { + $out = "CYBER AUDIT OWN INFRA:\n"; + $out .= "=== S204 nmap fast ===\n"; + $out .= @shell_exec("sudo nmap -T4 -F localhost 2>&1 | head -20"); + $out .= "\n=== SSL weval-consulting.com ===\n"; + $out .= @shell_exec("echo | openssl s_client -connect weval-consulting.com:443 -servername weval-consulting.com 2>&1 | openssl x509 -noout -dates 2>&1"); + $out .= "\n=== Listening services ===\n"; + $out .= @shell_exec("sudo ss -tlnp 2>&1 | head -20"); + return ['provider' => 'wevia-cyber', 'content' => $out, 'tool' => 'cyber_full_audit']; + } + + // CYBER-5: cyber_firewall_status + if (preg_match('/\b(firewall|ufw|iptables)\s+(status|check|list)/', $m)) { + $out = "FIREWALL STATUS:\n"; + $out .= @shell_exec("sudo ufw status 2>&1 | head -20"); + $out .= "\n=== iptables ===\n"; + $out .= @shell_exec("sudo iptables -L -n --line-numbers 2>&1 | head -30"); + return ['provider' => 'wevia-cyber', 'content' => $out, 'tool' => 'cyber_firewall_status']; + } + + // CYBER-6: cyber_fail2ban_status + if (preg_match('/\b(fail2ban|banned|bans|intrusion)/', $m)) { + $out = @shell_exec("sudo fail2ban-client status 2>&1 | head -10"); + if (!$out) $out = "fail2ban not installed"; + return ['provider' => 'wevia-cyber', 'content' => "FAIL2BAN: $out", 'tool' => 'cyber_fail2ban']; + } + + // CYBER-7: cyber_last_logins + if (preg_match('/\b(last\s+logins?|who\s+logged|auth\s+log|ssh\s+log)/', $m)) { + $out = @shell_exec("sudo last -n 10 2>&1"); + $out .= "\n=== SSH auth fails ===\n"; + $out .= @shell_exec("sudo grep -iE 'failed|invalid' /var/log/auth.log 2>&1 | tail -15"); + return ['provider' => 'wevia-cyber', 'content' => $out, 'tool' => 'cyber_last_logins']; + } + + // ═══════════ ARCHI DIRECT CONTROL ═══════════ + + // ARCHI-1: docker_control (start/stop/restart/logs) + if (preg_match('/\b(docker)\s+(start|stop|restart|logs|status|ps|inspect)\s+(\S+)?/', $m, $mt)) { + $action = $mt[2]; + $target = isset($mt[3]) ? escapeshellarg($mt[3]) : ''; + if ($action === 'ps' || $action === 'status') { + $out = @shell_exec("sudo docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' 2>&1 | head -25"); + } elseif ($action === 'logs') { + $out = @shell_exec("sudo docker logs --tail 30 $target 2>&1 | head -40"); + } elseif ($action === 'inspect') { + $out = @shell_exec("sudo docker inspect $target --format '{{json .State}}{{json .NetworkSettings.Ports}}' 2>&1 | head -20"); + } else { + // start/stop/restart + $out = @shell_exec("sudo docker $action $target 2>&1"); + } + return ['provider' => 'wevia-archi', 'content' => "DOCKER $action $target:\n$out", 'tool' => 'archi_docker_control']; + } + + // ARCHI-2: service_control (systemctl) + if (preg_match('/\b(service|systemctl)\s+(start|stop|restart|status|reload)\s+(\S+)/', $m, $mt)) { + $action = $mt[2]; + $target = escapeshellarg($mt[3]); + $out = @shell_exec("sudo systemctl $action $target 2>&1 | head -25"); + return ['provider' => 'wevia-archi', 'content' => "SYSTEMCTL $action $target:\n$out", 'tool' => 'archi_service_control']; + } + + // ARCHI-3: nginx_control (reload, test, vhost list) + if (preg_match('/\bnginx\s+(reload|test|vhosts?|sites|status)/', $m, $mt)) { + $action = $mt[1]; + if ($action === 'test') { + $out = @shell_exec("sudo nginx -t 2>&1"); + } elseif ($action === 'reload') { + $out = @shell_exec("sudo nginx -t 2>&1 && sudo nginx -s reload 2>&1"); + } elseif (in_array($action, ['vhosts', 'vhost', 'sites'])) { + $out = @shell_exec("sudo ls /etc/nginx/sites-enabled/ 2>&1 | head -30"); + } else { + $out = @shell_exec("sudo systemctl status nginx --no-pager 2>&1 | head -15"); + } + return ['provider' => 'wevia-archi', 'content' => "NGINX $action:\n$out", 'tool' => 'archi_nginx_control']; + } + + // ARCHI-4: s95_remote_exec (via sentinel) + if (preg_match('/\bs95\s+(exec|run|cmd)\s+(.+)/', $m, $mt)) { + $cmd = $mt[2]; + $out = @shell_exec("curl -s -u weval:W3valAdmin2026 -X POST http://10.1.0.3:5890/api/exec -H 'Content-Type: application/json' -d " . escapeshellarg(json_encode(['cmd' => $cmd])) . " 2>&1 | head -30"); + return ['provider' => 'wevia-archi', 'content' => "S95 EXEC: $cmd\n$out", 'tool' => 'archi_s95_exec']; + } + + // ARCHI-5: s151_health (OVH) + if (preg_match('/\bs151\s+(health|status|ping|check)/', $m)) { + $out = "S151 (OVH 151.80.235.110):\n"; + $out .= "ping: " . @shell_exec("ping -c 2 -W 2 151.80.235.110 2>&1 | tail -2"); + $out .= "tracking: HTTP " . @shell_exec("curl -s -o /dev/null -w '%{http_code}' -m 5 http://151.80.235.110/healthcheck 2>&1"); + return ['provider' => 'wevia-archi', 'content' => $out, 'tool' => 'archi_s151_health']; + } + + // ARCHI-6: disk_usage_detailed + if (preg_match('/\b(disk|disque)\s+(detail|usage|breakdown|top)/', $m)) { + $out = "DISK USAGE DETAIL:\n"; + $out .= @shell_exec("df -h / 2>&1 | tail -2"); + $out .= "\n=== Top 10 dirs /opt ===\n"; + $out .= @shell_exec("sudo du -sh /opt/* 2>/dev/null | sort -rh | head -10"); + $out .= "\n=== Top 10 dirs /var/www ===\n"; + $out .= @shell_exec("sudo du -sh /var/www/* 2>/dev/null | sort -rh | head -10"); + return ['provider' => 'wevia-archi', 'content' => $out, 'tool' => 'archi_disk_detail']; + } + + // ARCHI-7: process_kill (controlled) + if (preg_match('/\b(kill|stop)\s+(pid\s+)?(\d+)/', $m, $mt)) { + $pid = intval($mt[3]); + if ($pid < 100) return ['provider' => 'wevia-archi', 'content' => "REFUSED: PID $pid too low (system)", 'tool' => 'archi_process_kill']; + $out = @shell_exec("sudo kill -15 $pid 2>&1; sleep 1; ps -p $pid 2>&1"); + return ['provider' => 'wevia-archi', 'content' => "KILL PID $pid:\n$out", 'tool' => 'archi_process_kill']; + } + + // ARCHI-8: pg_direct_query (safe - read only S95) + if (preg_match('/\b(pg|postgres)\s+(query|select)\s+(.+)/', $m, $mt)) { + $q = $mt[3]; + // Safety: reject DROP/TRUNCATE/DELETE/UPDATE (only SELECT) + if (preg_match('/\b(DROP|TRUNCATE|DELETE|UPDATE|INSERT|ALTER)\b/i', $q)) { + return ['provider' => 'wevia-archi', 'content' => 'REFUSED: only SELECT allowed via pg direct - use explicit DB admin intent for writes', 'tool' => 'archi_pg_query']; + } + $esc_q = escapeshellarg($q); + $out = @shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -c $esc_q 2>&1 | head -30"); + return ['provider' => 'wevia-archi', 'content' => "PG QUERY: $q\n$out", 'tool' => 'archi_pg_query']; + } + + return null; // no match +} diff --git a/api/wevia-opus-intents.php b/api/wevia-opus-intents.php index 6de714fb7..43be97a6e 100644 --- a/api/wevia-opus-intents.php +++ b/api/wevia-opus-intents.php @@ -7,6 +7,15 @@ function wevia_opus_intents($msg) { $m = mb_strtolower(trim($msg)); $r = null; + // DOCTRINE 211 CYBER + ARCHI DIRECT CONTROL (priority BEFORE everything) + if (!function_exists('wevia_cyber_archi_dispatch')) { + @require_once __DIR__ . '/wevia-cyber-archi-control.php'; + } + if (function_exists('wevia_cyber_archi_dispatch')) { + $cyber_r = wevia_cyber_archi_dispatch($msg); + if ($cyber_r !== null) return $cyber_r; + } + // PLUGIN STORE AUTODISCOVERY (priority highest after init) if (function_exists('wevia_plugin_intents')) { $plugin_result = wevia_plugin_intents($msg);