187 lines
12 KiB
HTML
Executable File
187 lines
12 KiB
HTML
Executable File
<?php include_once("/opt/wevads-arsenal/public/api/wevads-metrics.php"); ?>
|
||
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>WEVADS - 🛡️ Sentinel V4 ULTRA</title>
|
||
<style>
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
:root{--bg:#0a0e17;--c1:#0f1520;--c2:#151c2c;--gn:#00ff88;--rd:#ff4466;--yl:#ffaa00;--cy:#00ddff;--pu:#aa66ff;--pk:#ff66aa;--t1:#e8ecf4;--t2:#8892a6;--brd:#1e2840}
|
||
body{background:var(--bg);color:var(--t1);font-family:'Segoe UI',system-ui,sans-serif;height:100vh;display:flex;flex-direction:column;overflow:hidden}
|
||
.top{display:flex;align-items:center;padding:8px 16px;background:var(--c1);border-bottom:1px solid var(--brd);gap:12px;flex-shrink:0}
|
||
.top h1{font-size:15px;font-weight:700;color:var(--gn)}
|
||
.top .badge{background:var(--gn);color:#e2e8f0;padding:2px 8px;border-radius:10px;font-size:9px;font-weight:700}
|
||
.top .score{margin-left:auto;font-size:20px;font-weight:800;color:var(--gn)}
|
||
.main{display:flex;flex:1;overflow:hidden}
|
||
.left{flex:1;display:flex;flex-direction:column;overflow:hidden;border-right:1px solid var(--brd)}
|
||
.right{width:380px;display:flex;flex-direction:column;background:var(--c1)}
|
||
.stats{display:grid;grid-template-columns:repeat(6,1fr);gap:6px;padding:8px;flex-shrink:0}
|
||
.stat{background:var(--c2);border:1px solid var(--brd);border-radius:6px;padding:8px;text-align:center}
|
||
.stat .n{font-size:20px;font-weight:800}.stat .l{font-size:8px;color:var(--t2);margin-top:2px}
|
||
.panels{display:grid;grid-template-columns:1fr 1fr;gap:6px;padding:0 8px 8px;flex:1;overflow:hidden}
|
||
.panel{background:var(--c2);border:1px solid var(--brd);border-radius:6px;display:flex;flex-direction:column;overflow:hidden}
|
||
.panel h3{font-size:10px;padding:6px 10px;background:rgba(0,255,136,0.05);border-bottom:1px solid var(--brd);color:var(--gn);flex-shrink:0}
|
||
.panel .content{flex:1;overflow-y:auto;padding:6px 8px;font-size:9px;font-family:'JetBrains Mono',monospace;line-height:1.6}
|
||
.issue{padding:4px 6px;margin:2px 0;border-radius:3px;border-left:3px solid var(--yl)}
|
||
.issue.critical{border-color:var(--rd);background:rgba(255,68,102,0.05)}
|
||
.issue.ok{border-color:var(--gn);background:rgba(0,255,136,0.05)}
|
||
.fix{padding:3px 6px;margin:2px 0;border-left:2px solid var(--pu)}
|
||
.pattern{display:flex;justify-content:space-between;padding:3px 6px;border-bottom:1px solid var(--brd)}
|
||
.pattern .cnt{color:var(--cy);font-weight:700}
|
||
.chat-head{padding:8px 12px;border-bottom:1px solid var(--brd);font-size:11px;font-weight:700;color:var(--gn);display:flex;align-items:center;gap:8px}
|
||
.chat-head .prov{margin-left:auto;font-size:8px;color:var(--t2)}
|
||
.chat-msgs{flex:1;overflow-y:auto;padding:8px}
|
||
.msg{margin:6px 0;padding:8px 10px;border-radius:8px;font-size:10px;line-height:1.5;white-space:pre-wrap;word-break:break-word}
|
||
.msg.u{background:var(--c2);border:1px solid var(--brd);margin-left:40px}
|
||
.msg.s{background:rgba(0,255,136,0.06);border:1px solid rgba(0,255,136,0.15);margin-right:20px}
|
||
.msg .hdr{font-size:8px;color:var(--t2);margin-bottom:4px}
|
||
.qbtns{display:flex;flex-wrap:wrap;gap:4px;padding:6px 8px;border-top:1px solid var(--brd);flex-shrink:0}
|
||
.qb{background:var(--c2);border:1px solid var(--brd);color:var(--cy);padding:4px 8px;border-radius:12px;font-size:8px;cursor:pointer}
|
||
.qb:hover{background:rgba(0,221,255,0.1);border-color:var(--cy)}
|
||
.chi{display:flex;padding:6px 8px;gap:6px;border-top:1px solid var(--brd);flex-shrink:0}
|
||
.chi input{flex:1;background:var(--c2);border:1px solid var(--brd);color:var(--t1);padding:8px 12px;border-radius:6px;font-size:11px;outline:none}
|
||
.chi input:focus{border-color:var(--gn)}
|
||
.chi button{background:var(--gn);color:#e2e8f0;border:none;padding:8px 16px;border-radius:6px;font-weight:700;cursor:pointer;font-size:11px}
|
||
.ld{display:inline-block;width:12px;height:12px;border:2px solid var(--gn);border-top-color:transparent;border-radius:50%;animation:spin 0.8s linear infinite}
|
||
@keyframes spin{to{transform:rotate(360deg)}}
|
||
.gn{color:var(--gn)}.rd{color:var(--rd)}.yl{color:var(--yl)}.cy{color:var(--cy)}.pu{color:var(--pu)}
|
||
.wv-status{position:fixed;top:12px;right:140px;z-index:9998;background:rgba(52,211,153,.15);border:1px solid #34d399;border-radius:12px;padding:3px 10px;color:#34d399;font-size:10px;font-weight:700;font-family:'JetBrains Mono',monospace}
|
||
|
||
.sc,.card,[class*="stat-card"]{transition:all .25s ease;position:relative;overflow:hidden}
|
||
.sc:hover,.card:hover,[class*="stat-card"]:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.25)}
|
||
.sc::after,.card::after{content:'';position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--cy,#22d3ee);opacity:0;transition:opacity .25s}
|
||
.sc:hover::after,.card:hover::after{opacity:.7}
|
||
.btn,.button,[class*="btn-"]{transition:all .2s ease}
|
||
.btn:hover,.button:hover{transform:translateY(-1px)}
|
||
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
|
||
.sc,.card{animation:fadeIn .4s ease both}
|
||
.sc:nth-child(2),.card:nth-child(2){animation-delay:.05s}
|
||
.sc:nth-child(3),.card:nth-child(3){animation-delay:.1s}
|
||
.sc:nth-child(4),.card:nth-child(4){animation-delay:.15s}
|
||
.sc:nth-child(5),.card:nth-child(5){animation-delay:.2s}
|
||
.sc:nth-child(6),.card:nth-child(6){animation-delay:.25s}
|
||
</style>
|
||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=DM+Sans:wght@400;600;700&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="wevads-global.css?v1770777318">
|
||
</head>
|
||
<body>
|
||
|
||
|
||
<div class="top">
|
||
<h1>🛡️ SENTINEL V4 ULTRA</h1>
|
||
<span class="badge">REGRESSION GUARD</span>
|
||
<span style="font-size:9px;color:var(--t2)">SSH 3 Servers • Vault Guard • Anti-Regression • Auto-Repair</span>
|
||
<span class="score" id="topScore">—%</span>
|
||
</div>
|
||
<div class="main">
|
||
<div class="left">
|
||
<div class="stats">
|
||
<div class="stat"><div class="n gn" id="sScore">—</div><div class="l">SCORE</div></div>
|
||
<div class="stat"><div class="n cy" id="sFiles">—</div><div class="l">FILES</div></div>
|
||
<div class="stat"><div class="n yl" id="sIssues">—</div><div class="l">ISSUES</div></div>
|
||
<div class="stat"><div class="n pu" id="sFixes">—</div><div class="l">FIXES</div></div>
|
||
<div class="stat"><div class="n" id="sPatterns">—</div><div class="l">PATTERNS</div></div>
|
||
<div class="stat"><div class="n" id="sVault">—</div><div class="l">VAULT RESTORES</div></div>
|
||
</div>
|
||
<div class="panels">
|
||
<div class="panel"><h3>📜 SCAN HISTORY</h3><div class="content" id="pHistory">Loading...</div></div>
|
||
<div class="panel"><h3>🧠 ACTIVE PATTERNS</h3><div class="content" id="pPatterns">Loading...</div></div>
|
||
<div class="panel"><h3>🔧 RECENT FIXES</h3><div class="content" id="pFixes">Loading...</div></div>
|
||
<div class="panel"><h3>🔒 VAULT GUARD LOG</h3><div class="content" id="pVault">Loading...</div></div>
|
||
</div>
|
||
</div>
|
||
<div class="right">
|
||
<div class="chat-head">
|
||
🛡️ Sentinel V4 Chat <span class="prov" id="chatProv">—</span>
|
||
</div>
|
||
<div class="chat-msgs" id="chatMsgs">
|
||
<div class="msg s"><div class="hdr">🛡️ Sentinel V4 ULTRA</div>SSH réel • Anti-hallucination actif • Vault Guard intégré
|
||
Commandes: scan, fix, status, ports, exec [cmd], vault check, regression scan
|
||
Servers: Hetzner (local) + OVH (SSH) + Consulting (SSH)</div>
|
||
</div>
|
||
<div class="qbtns">
|
||
<div class="qb" data-q="scan complet avec regression">🔍 Full Scan</div>
|
||
<div class="qb" data-q="fix tous les problèmes">🔧 Auto-Fix</div>
|
||
<div class="qb" data-q="status tous serveurs">📊 Status</div>
|
||
<div class="qb" data-q="vérifie tracking OVH end-to-end">📡 Tracking</div>
|
||
<div class="qb" data-q="vault check integrity">🔒 Vault</div>
|
||
<div class="qb" data-q="vérifie placeholders brain configs">🧠 —s</div>
|
||
<div class="qb" data-q="disk mémoire load tous serveurs">💾 Resources</div>
|
||
<div class="qb" data-q="ports et services actifs">🔌 Ports</div>
|
||
<div class="qb" data-q="vérifie brain-inject.js headers">📧 Headers</div>
|
||
<div class="qb" data-q="test e2e tracking complet">🧪 E2E Test</div>
|
||
</div>
|
||
<div class="chi">
|
||
<input id="cI" placeholder="Commande Sentinel...">
|
||
<button id="btnSend">→</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
var API='/api/sentinel-brain.php';
|
||
function $(id){return document.getElementById(id)}
|
||
function addMsg(txt,type,provider){
|
||
var d=document.createElement('div');d.className='msg '+type;
|
||
if(type==='s'&&provider)txt='<div class="hdr">🛡️ '+provider+'</div>'+txt;
|
||
d.innerHTML=txt;$('chatMsgs').appendChild(d);d.scrollIntoView({behavior:'smooth'});
|
||
}
|
||
function sendChat(){
|
||
var inp=$('cI'),msg=inp.value.trim();if(!msg)return;
|
||
inp.value='';addMsg(msg,'u');
|
||
var ld=document.createElement('div');ld.className='msg s';ld.innerHTML='<span class="ld"></span> Exécution SSH réelle...';
|
||
$('chatMsgs').appendChild(ld);ld.scrollIntoView({behavior:'smooth'});
|
||
var fd=new FormData();fd.append('action','chat');fd.append('message',msg);
|
||
fetch(API,{method:'POST',body:fd}).then(r=>r.json()).then(d=>{
|
||
ld.remove();$('chatProv').textContent=d.provider||'';
|
||
addMsg((d.response||'Erreur').replace(/</g,'<').replace(/>/g,'>').replace(/`([^`]+)`/g,'<span style="color:var(--cy)">$1</span>').replace(/(✅|❌|⚠️|🖥️|📡|🏢|💻)/g,'<br>$1'),'s',d.provider);
|
||
loadDashboard();
|
||
}).catch(e=>{ld.remove();addMsg('❌ Erreur: '+e.message,'s');});
|
||
}
|
||
function loadDashboard(){
|
||
// Status
|
||
fetch(API+'?action=status').then(r=>r.json()).then(d=>{
|
||
$('topScore').textContent=(d.last_scan?.score||'—')+'%';
|
||
$('topScore').style.color=parseFloat(d.last_scan?.score||0)>=95?'var(--gn)':parseFloat(d.last_scan?.score||0)>=85?'var(--yl)':'var(--rd)';
|
||
$('sScore').textContent=(d.last_scan?.score||'—')+'%';
|
||
$('sFiles').textContent=d.last_scan?.total_files||'—';
|
||
$('sIssues').textContent=d.last_scan?.issues_found||'—';
|
||
$('sFixes').textContent=d.total_fixes||'—';
|
||
$('sPatterns').textContent=(d.patterns||[]).filter(p=>p.times_detected>0).length;
|
||
// Patterns
|
||
var ph='';(d.patterns||[]).forEach(p=>{if(p.times_detected>0)ph+='<div class="pattern"><span>'+p.pattern_name+'</span><span class="cnt">×'+p.times_detected+'</span></div>';});
|
||
$('pPatterns').innerHTML=ph||'<div style="color:var(--t2)">No active patterns</div>';
|
||
}).catch(()=>{});
|
||
// History
|
||
fetch(API+'?action=history&limit=15').then(r=>r.json()).then(d=>{
|
||
var h='';(d.scans||[]).forEach(s=>{
|
||
var cl=parseFloat(s.score)>=95?'gn':parseFloat(s.score)>=85?'yl':'rd';
|
||
h+='<div class="issue '+(parseFloat(s.score)>=95?'ok':'')+'"><span class="'+cl+'">'+s.score+'%</span> | '+s.total_files+' files | '+s.issues_found+' issues | '+s.issues_fixed+' fixed<br><span style="color:var(--t2)">'+s.scan_date?.substr(0,19)+'</span></div>';
|
||
});$('pHistory').innerHTML=h||'No scans yet';
|
||
}).catch(()=>{});
|
||
// Fixes
|
||
fetch(API+'?action=fixes&limit=20').then(r=>r.json()).then(d=>{
|
||
var f='';(d.fixes||[]).forEach(x=>{
|
||
f+='<div class="fix"><span class="pu">'+x.fix_type+'</span> '+x.file_path?.split('/').pop()+'<br><span style="color:var(--t2)">'+x.fix_detail+'</span></div>';
|
||
});$('pFixes').innerHTML=f||'No fixes yet';
|
||
}).catch(()=>{});
|
||
// Vault
|
||
fetch('/api/vault-guard.php?action=status').then(r=>r.json()).then(d=>{
|
||
$('sVault').textContent=d.total_restores||0;
|
||
var v='<div style="margin-bottom:6px">Vault: '+d.vault_files+' files | Healthy: '+d.healthy+' | Truncated: <span class="'+(d.truncated>0?'rd':'gn')+'">'+d.truncated+'</span></div>';
|
||
(d.last_restores||[]).forEach(r=>{v+='<div class="fix"><span class="rd">'+r.issue_type+'</span> '+r.file_path?.split('/').pop()+'<br><span style="color:var(--t2)">'+r.created_at+'</span></div>';});
|
||
(d.issues||[]).forEach(i=>{v+='<div class="issue critical">'+i.file?.split('/').pop()+': '+i.status+' ('+i.loss_pct+'% lost)</div>';});
|
||
$('pVault').innerHTML=v;
|
||
}).catch(()=>{});
|
||
}
|
||
$('btnSend').onclick=sendChat;
|
||
$('cI').onkeydown=function(e){if(e.key==='Enter')sendChat()};
|
||
document.querySelectorAll('.qb').forEach(b=>b.onclick=function(){$('cI').value=b.dataset.q;sendChat()});
|
||
loadDashboard();setInterval(loadDashboard,60000);
|
||
</script>
|
||
<script src="arsenal-common.js?v1770778169">
|
||
<?php include("/opt/wevads-arsenal/public/universal-drill.html"); ?>
|
||
</body>
|
||
</html></script>
|