auto-sync-opus46
53
exhaustive_audit.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
echo "=== 1. NR cache fresh ==="
|
||||
AGE=$(($(date +%s) - $(stat -c %Y /tmp/l99-honest-cache.json 2>/dev/null || echo 0)))
|
||||
echo "age: ${AGE}s"
|
||||
if [ $AGE -gt 1800 ]; then
|
||||
rm -f /tmp/l99-honest-cache.json /tmp/l99-honest.lock
|
||||
nohup bash /var/www/html/api/handlers/l99-honest-refresh.sh > /tmp/l99_v88.txt 2>&1 &
|
||||
echo "REFRESH KICKED pid=$!"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== 2. WTP HTTP check ==="
|
||||
curl -s "https://weval-consulting.com/weval-technology-platform.html" --max-time 10 -o /dev/null -w "WTP: HTTP=%{http_code} size=%{size_download} time=%{time_total}s\n"
|
||||
|
||||
echo ""
|
||||
echo "=== 3. Recent 5xx count (last 1000 log lines) ==="
|
||||
sudo -n tail -1000 /var/log/nginx/access.log 2>/dev/null | awk '$9 ~ /^5/ {c[$9]++} END {for (k in c) print k, c[k]}'
|
||||
|
||||
echo ""
|
||||
echo "=== 4. Recent 404 count (last 1000 log lines) on /api/ ==="
|
||||
sudo -n tail -1000 /var/log/nginx/access.log 2>/dev/null | awk '$9 == "404" && $7 ~ /^\/api\// {c[$7]++} END {for (k in c) print c[k], k}' | sort -rn | head -10
|
||||
|
||||
echo ""
|
||||
echo "=== 5. PHP errors last 50 lines ==="
|
||||
sudo -n tail -50 /var/log/php8.5-fpm.log 2>/dev/null | grep -v "NOTICE\|^$" | tail -10
|
||||
|
||||
echo ""
|
||||
echo "=== 6. Long-running FPM children ==="
|
||||
ps auxw | grep "php-fpm" | awk '$10 > "1:00" {print $2, $10, $11, $12}' | head -5
|
||||
|
||||
echo ""
|
||||
echo "=== 7. Docker health ==="
|
||||
docker ps --format "{{.Names}}: {{.Status}}" 2>/dev/null | grep -v "healthy\|Up [0-9]" | head -5
|
||||
|
||||
echo ""
|
||||
echo "=== 8. Load avg ==="
|
||||
uptime
|
||||
|
||||
echo ""
|
||||
echo "=== 9. Memory ==="
|
||||
free -h | head -2
|
||||
|
||||
echo ""
|
||||
echo "=== 10. Critical API endpoints ==="
|
||||
for ep in \
|
||||
"/api/l99-honest.php" \
|
||||
"/api/weval-archi-manifest.php" \
|
||||
"/api/wevia-v64-departments-kpi.php" \
|
||||
"/api/wevia-master-api.php" \
|
||||
"/api/em-live-kpi.php"; do
|
||||
T=$(curl -s "http://127.0.0.1${ep}" -H "Host: weval-consulting.com" --max-time 5 -o /dev/null -w "%{http_code} %{time_total}s")
|
||||
echo "$ep -> $T"
|
||||
done
|
||||
60
fix_api_error.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
path = "/etc/nginx/sites-enabled/weval-consulting"
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
|
||||
if b"location @api_error" in raw:
|
||||
print("ALREADY")
|
||||
exit(0)
|
||||
|
||||
# Find the FIRST "server {" and its closing "}"
|
||||
# Server 1 goes from line 7 to line 55 per grep
|
||||
# Insert @api_error definition BEFORE the closing "}" of server 1
|
||||
|
||||
# Find line "^}\n" that comes after line with "error_page 502 503 504 =503 @api_error"
|
||||
# Pattern: first standalone closing brace after @api_error usage
|
||||
|
||||
# Split into lines with byte offsets
|
||||
lines = raw.split(b"\n")
|
||||
|
||||
# Find @api_error first usage
|
||||
api_err_line = None
|
||||
for i, ln in enumerate(lines):
|
||||
if b"@api_error" in ln:
|
||||
api_err_line = i
|
||||
break
|
||||
|
||||
# Find first standalone "}" after that
|
||||
close_line = None
|
||||
for i in range(api_err_line, len(lines)):
|
||||
if lines[i].strip() == b"}":
|
||||
close_line = i
|
||||
break
|
||||
|
||||
if close_line is None:
|
||||
print("NO_CLOSE")
|
||||
exit(1)
|
||||
|
||||
# Insert @api_error location before close_line
|
||||
insert = [
|
||||
b"",
|
||||
b" # V88: named location @api_error - JSON error for API FastCGI failures",
|
||||
b" location @api_error {",
|
||||
b" default_type application/json;",
|
||||
b" return 503 '{\"ok\":false,\"error\":\"api_error\",\"upstream\":\"fpm\",\"msg\":\"service temporarily unavailable\"}';",
|
||||
b" }",
|
||||
b"",
|
||||
]
|
||||
|
||||
lines = lines[:close_line] + insert + lines[close_line:]
|
||||
new_raw = b"\n".join(lines)
|
||||
with open(path, "wb") as f:
|
||||
f.write(new_raw)
|
||||
print(f"Inserted @api_error at line {close_line}")
|
||||
print(f"Size: {len(raw)} → {len(new_raw)}")
|
||||
|
||||
# Also insert in server 2 (HTTPS) if same issue
|
||||
# Find second @api_error
|
||||
idx2 = new_raw.find(b"@api_error", new_raw.find(b"@api_error") + 15)
|
||||
# Check if server 2 needs it too (we check if @api_error location is present in server 2)
|
||||
# For safety, insert also in HTTPS block
|
||||
42
fix_api_error_v2.py
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
path = "/etc/nginx/sites-enabled/weval-consulting"
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
|
||||
# Check if server 1 has @api_error location
|
||||
# Server 1 goes from line 7 to first "}" after line 33
|
||||
lines = raw.split(b"\n")
|
||||
|
||||
# Line 6 = index 6 (0-indexed line 7)
|
||||
# Find server 1 close - first standalone "}" after line 33
|
||||
close_line = None
|
||||
for i in range(33, 80): # Look between line 33 and ~80
|
||||
if i < len(lines) and lines[i].strip() == b"}":
|
||||
close_line = i
|
||||
break
|
||||
|
||||
print(f"Server 1 close at line: {close_line+1}")
|
||||
|
||||
# Check if @api_error is already in server 1 (between lines 7-close_line)
|
||||
server1 = b"\n".join(lines[6:close_line+1])
|
||||
if b"location @api_error" in server1:
|
||||
print("Server 1 already has @api_error")
|
||||
exit(0)
|
||||
|
||||
# Insert location @api_error BEFORE close_line
|
||||
insert = [
|
||||
b"",
|
||||
b" # V88: named location @api_error for server 1 (HTTP)",
|
||||
b" location @api_error {",
|
||||
b" default_type application/json;",
|
||||
b" return 503 '{\"ok\":false,\"error\":\"api_error\",\"msg\":\"service temporarily unavailable\"}';",
|
||||
b" }",
|
||||
b"",
|
||||
]
|
||||
|
||||
lines = lines[:close_line] + insert + lines[close_line:]
|
||||
new_raw = b"\n".join(lines)
|
||||
with open(path, "wb") as f:
|
||||
f.write(new_raw)
|
||||
print(f"Inserted @api_error at line {close_line+1}")
|
||||
print(f"Size: {len(raw)} → {len(new_raw)}")
|
||||
47
fix_api_error_v3.py
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
path = "/etc/nginx/sites-enabled/weval-consulting"
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
|
||||
lines = raw.split(b"\n")
|
||||
|
||||
# Find server 1 end: last "}" BEFORE second "server {"
|
||||
server_opens = []
|
||||
for i, ln in enumerate(lines):
|
||||
if ln.strip() == b"server {":
|
||||
server_opens.append(i)
|
||||
|
||||
print(f"Server opens at lines: {[x+1 for x in server_opens]}")
|
||||
|
||||
# Server 1: lines[server_opens[0]] to last "}" before server_opens[1]
|
||||
# Scan backwards from server_opens[1]-1 to find closing brace at col 0
|
||||
server1_close = None
|
||||
for i in range(server_opens[1]-1, server_opens[0], -1):
|
||||
if lines[i].strip() == b"}":
|
||||
server1_close = i
|
||||
break
|
||||
|
||||
print(f"Server 1 close at line {server1_close+1}")
|
||||
|
||||
# Check if server 1 already has @api_error location
|
||||
server1 = b"\n".join(lines[server_opens[0]:server1_close+1])
|
||||
if b"location @api_error" in server1:
|
||||
print("Server 1 already has @api_error - aborting")
|
||||
exit(0)
|
||||
|
||||
insert = [
|
||||
b"",
|
||||
b" # V88: named location @api_error - JSON error for API FastCGI failures",
|
||||
b" location @api_error {",
|
||||
b" default_type application/json;",
|
||||
b" return 503 '{\"ok\":false,\"error\":\"api_error\",\"msg\":\"service temporarily unavailable\"}';",
|
||||
b" }",
|
||||
b"",
|
||||
]
|
||||
|
||||
lines = lines[:server1_close] + insert + lines[server1_close:]
|
||||
new_raw = b"\n".join(lines)
|
||||
with open(path, "wb") as f:
|
||||
f.write(new_raw)
|
||||
print(f"Inserted @api_error at line {server1_close+1}")
|
||||
print(f"Size: {len(raw)} → {len(new_raw)}")
|
||||
44
fix_autoheal.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
# V88: Fix wevia-auto-heal (raise worker threshold) + wevia-master-autoheal (timings)
|
||||
|
||||
# Fix 1: auto-heal threshold
|
||||
path1 = "/var/www/html/api/wevia-auto-heal.php"
|
||||
with open(path1, "rb") as f:
|
||||
raw1 = f.read()
|
||||
|
||||
if b"V88" not in raw1:
|
||||
# Change threshold 50 → 180 (max is 140 total pools = safe headroom)
|
||||
old = b"$w > 50"
|
||||
new = b"$w > 180" # V88: raised from 50 to 180 (total max = 140 workers)
|
||||
if old in raw1:
|
||||
raw1 = raw1.replace(old, new, 1)
|
||||
# Also skip the self-kill - instead just log + call FPM reload via systemctl
|
||||
old_kill = b'shell_exec("killall -9 php-fpm8.5; sleep 2; systemctl start php8.5-fpm &")'
|
||||
new_kill = b'/* V88: disabled self-kill. Use systemctl reload instead */ shell_exec("sudo -n systemctl reload php8.5-fpm 2>&1 > /tmp/fpm-reload.log &")'
|
||||
if old_kill in raw1:
|
||||
raw1 = raw1.replace(old_kill, new_kill, 1)
|
||||
with open(path1, "wb") as f:
|
||||
f.write(raw1)
|
||||
print(f"auto-heal: size={len(raw1)}")
|
||||
|
||||
# Fix 2: master-autoheal timings
|
||||
path2 = "/var/www/html/api/wevia-master-autoheal.php"
|
||||
with open(path2, "rb") as f:
|
||||
raw2 = f.read()
|
||||
|
||||
if b"V88 hardened" not in raw2:
|
||||
old = b"<?php"
|
||||
new = b"""<?php
|
||||
// V88 hardened: limits to avoid fcgi timeout
|
||||
@set_time_limit(60);
|
||||
@ini_set('memory_limit', '256M');
|
||||
@ini_set('max_execution_time', 60);
|
||||
"""
|
||||
if old in raw2 and raw2.count(b"V88 hardened") == 0:
|
||||
idx = raw2.find(old)
|
||||
raw2 = raw2[:idx] + new + raw2[idx+len(old):]
|
||||
with open(path2, "wb") as f:
|
||||
f.write(raw2)
|
||||
print(f"master-autoheal: size={len(raw2)}")
|
||||
|
||||
print("DONE")
|
||||
15
fix_em_live_ttl.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
path = "/var/www/html/api/em-live-kpi.php"
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
|
||||
# Change TTL 5s -> 60s
|
||||
old = b"(time() - filemtime($_emcache)) < 5)"
|
||||
new = b"(time() - filemtime($_emcache)) < 60)"
|
||||
if old in raw:
|
||||
raw = raw.replace(old, new, 1)
|
||||
with open(path, "wb") as f:
|
||||
f.write(raw)
|
||||
print("TTL 5s -> 60s PATCHED")
|
||||
else:
|
||||
print("NOT_FOUND")
|
||||
27
fix_fpm_dedup_all.py
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
path = "/etc/php/8.5/fpm/pool.d/www.conf"
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
|
||||
# Dedup all active pm.* lines
|
||||
keywords = [b"pm.start_servers", b"pm.min_spare_servers", b"pm.max_spare_servers", b"pm.max_children"]
|
||||
lines = raw.split(b'\n')
|
||||
seen = {}
|
||||
kept = []
|
||||
for line in lines:
|
||||
stripped = line.strip()
|
||||
matched = None
|
||||
for kw in keywords:
|
||||
if stripped.startswith(kw + b" ") and not stripped.startswith(b";"):
|
||||
matched = kw
|
||||
break
|
||||
if matched:
|
||||
if matched in seen:
|
||||
continue
|
||||
seen[matched] = True
|
||||
kept.append(line)
|
||||
|
||||
new_raw = b'\n'.join(kept)
|
||||
with open(path, "wb") as f:
|
||||
f.write(new_raw)
|
||||
print(f"size: {len(raw)} -> {len(new_raw)}")
|
||||
35
fix_searxng_proxy.py
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
path = "/var/www/html/api/searxng-proxy.php"
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
|
||||
if b"V88 hardened" in raw:
|
||||
print("ALREADY")
|
||||
exit(0)
|
||||
|
||||
# After <?php tag - add safety limits
|
||||
old = b"<?php"
|
||||
new = b"""<?php
|
||||
// V88 hardened: limits + error handling
|
||||
@set_time_limit(20);
|
||||
@ini_set('memory_limit', '128M');
|
||||
@ini_set('max_execution_time', 20);
|
||||
"""
|
||||
if old in raw and raw.count(b"V88 hardened") == 0:
|
||||
idx = raw.find(old)
|
||||
raw = raw[:idx] + new + raw[idx+len(old):]
|
||||
|
||||
# Also wrap curl_exec with error capture
|
||||
old2 = b"$r = curl_exec($ch);\ncurl_close($ch);\necho $r ?: '{\"error\":\"searxng down\"}';"
|
||||
new2 = b"""$r = curl_exec($ch);
|
||||
$err = curl_error($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($r === false || $err) { echo json_encode(['error'=>'searxng down', 'curl_err'=>$err, 'http_code'=>$code]); exit; }
|
||||
echo $r;"""
|
||||
if old2 in raw:
|
||||
raw = raw.replace(old2, new2, 1)
|
||||
|
||||
with open(path, "wb") as f:
|
||||
f.write(raw)
|
||||
print(f"Size: {len(raw)}")
|
||||
13
install_l99_cron.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
# V88: Install L99 auto-refresh cron (15min interval)
|
||||
CRONBAK=$(crontab -l 2>/dev/null)
|
||||
echo "$CRONBAK" > /tmp/cron_before.txt
|
||||
if echo "$CRONBAK" | grep -q "l99-honest-refresh.sh"; then
|
||||
echo "ALREADY_CRONNED"
|
||||
exit 0
|
||||
fi
|
||||
(echo "$CRONBAK"; \
|
||||
echo "# V88 L99 honest auto-refresh every 15min (TTL 1200s = 20min)"; \
|
||||
echo "*/15 * * * * timeout 700 bash /var/www/html/api/handlers/l99-honest-refresh.sh >> /var/log/l99-honest-cron.log 2>&1") | crontab -
|
||||
echo "CRON_INSTALLED"
|
||||
crontab -l | grep -i l99
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"timestamp": "2026-04-20T14:10:02.132388",
|
||||
"timestamp": "2026-04-20T14:25:02.558886",
|
||||
"layers": {
|
||||
"DOCKER": {
|
||||
"pass": 19,
|
||||
@@ -17,8 +17,8 @@
|
||||
"pct": 100
|
||||
},
|
||||
"CRONS": {
|
||||
"pass": 34,
|
||||
"total": 34,
|
||||
"pass": 35,
|
||||
"total": 35,
|
||||
"pct": 100
|
||||
},
|
||||
"NONREG": {
|
||||
@@ -62,10 +62,10 @@
|
||||
"pct": 100
|
||||
}
|
||||
},
|
||||
"pass": 339,
|
||||
"pass": 340,
|
||||
"fail": 0,
|
||||
"warn": 0,
|
||||
"total": 339,
|
||||
"total": 340,
|
||||
"score": 100,
|
||||
"videos": 32,
|
||||
"screenshots": 14,
|
||||
|
||||
125
logs/alive-20260420-142736.log
Normal file
@@ -0,0 +1,125 @@
|
||||
[14:27:36] 🚀 L99-ALIVE v1.0 starting...
|
||||
[14:27:36] Time: 2026-04-20T14:27:36.863459
|
||||
[14:27:36] 🔍 PHASE 1: Detecting changes...
|
||||
[14:27:36] Scanning HTML pages...
|
||||
[14:27:37] ✅ [CHANGE-DETECT] changed 404.html — old=4749 new=8144
|
||||
[14:27:37] ✅ [CHANGE-DETECT] new page acquired-dashboard.html — size=35604
|
||||
[14:27:37] ✅ [CHANGE-DETECT] changed admin-saas.html — old=1683 new=1821
|
||||
[14:27:38] ✅ [CHANGE-DETECT] changed admin-v2.html — old=1683 new=1821
|
||||
[14:27:38] ✅ [CHANGE-DETECT] changed admin.html — old=1683 new=1821
|
||||
[14:27:38] ✅ [CHANGE-DETECT] new page agent-roi-simulator.html — size=33588
|
||||
[14:27:38] ✅ [CHANGE-DETECT] changed agents-3d.html — old=1683 new=1821
|
||||
[14:27:39] ✅ [CHANGE-DETECT] changed agents-alive.html — old=1683 new=1821
|
||||
[14:27:39] ✅ [CHANGE-DETECT] changed agents-archi.html — old=1683 new=1821
|
||||
[14:27:39] ✅ [CHANGE-DETECT] changed agents-final.html — old=1683 new=1821
|
||||
[14:27:40] ✅ [CHANGE-DETECT] changed agents-fleet.html — old=1683 new=1821
|
||||
[14:27:40] ✅ [CHANGE-DETECT] changed agents-goodjob.html — old=1683 new=1821
|
||||
[14:27:41] ✅ [CHANGE-DETECT] changed agents-hd.html — old=1683 new=1821
|
||||
[14:27:41] ✅ [CHANGE-DETECT] changed agents-hd2.html — old=1683 new=1821
|
||||
[14:27:41] ✅ [CHANGE-DETECT] changed agents-hub.html — old=9259 new=1821
|
||||
[14:27:42] ✅ [CHANGE-DETECT] changed agents-ia.html — old=1683 new=1821
|
||||
[14:27:42] ✅ [CHANGE-DETECT] changed agents-iso3d.html — old=1683 new=1821
|
||||
[14:27:43] ✅ [CHANGE-DETECT] new page agents-unified-registry.html — size=1821
|
||||
[14:27:43] ✅ [CHANGE-DETECT] changed agents-valuechain.html — old=1683 new=1821
|
||||
[14:27:43] ✅ [CHANGE-DETECT] changed ai-benchmark.html — old=1683 new=1821
|
||||
[14:27:43] ✅ [CHANGE-DETECT] changed ai-hub.html — old=17398 new=21039
|
||||
[14:27:44] ✅ [CHANGE-DETECT] changed all-screens-live.html — old=72 new=1821
|
||||
[14:27:44] ✅ [CHANGE-DETECT] changed anthropic-hub.html — old=6227 new=1821
|
||||
[14:27:44] ✅ [CHANGE-DETECT] changed api-key-hub.html — old=12517 new=16158
|
||||
[14:27:45] ✅ [CHANGE-DETECT] changed apps.html — old=1683 new=1821
|
||||
[14:27:45] ✅ [CHANGE-DETECT] changed architecture-live.html — old=32116 new=1821
|
||||
[14:27:45] ✅ [CHANGE-DETECT] changed architecture-map.html — old=31488 new=1821
|
||||
[14:27:46] ✅ [CHANGE-DETECT] changed architecture.html — old=51850 new=1821
|
||||
[14:27:46] ✅ [CHANGE-DETECT] changed arsenal-login.html — old=6431 new=1821
|
||||
[14:27:46] ✅ [CHANGE-DETECT] changed arsenal-offline.html — old=3064 new=6459
|
||||
[14:27:47] ✅ [CHANGE-DETECT] new page automation-hub.html — size=1821
|
||||
[14:27:47] ✅ [CHANGE-DETECT] changed avatar-picker.html — old=11373 new=1821
|
||||
[14:27:48] ✅ [CHANGE-DETECT] new page azure-reregister.html — size=1821
|
||||
[14:27:48] ✅ [CHANGE-DETECT] new page blade-actions.html — size=1821
|
||||
[14:27:49] ✅ [CHANGE-DETECT] changed blade-ai.html — old=1683 new=1821
|
||||
[14:27:49] ✅ [CHANGE-DETECT] changed blade-center.html — old=1683 new=1821
|
||||
[14:27:49] ✅ [CHANGE-DETECT] new page blade-control.html — size=1821
|
||||
[14:27:50] ✅ [CHANGE-DETECT] changed blade-hub.html — old=8868 new=12318
|
||||
[14:27:50] ✅ [CHANGE-DETECT] changed blade-install.html — old=1683 new=1821
|
||||
[14:27:50] ✅ [CHANGE-DETECT] changed booking.html — old=9404 new=12961
|
||||
[14:27:50] ✅ [CHANGE-DETECT] changed bpmn-studio-NEW.html — old=6014 new=1821
|
||||
[14:27:51] ✅ [CHANGE-DETECT] changed bpmn-studio-live.html — old=7435 new=1821
|
||||
[14:27:51] ✅ [CHANGE-DETECT] changed brain-center-tenant.html — old=5110 new=1821
|
||||
[14:27:51] ✅ [CHANGE-DETECT] new page candidate-detail.html — size=1821
|
||||
[14:27:52] ✅ [CHANGE-DETECT] new page candidates-pool.html — size=1821
|
||||
[14:27:52] ✅ [CHANGE-DETECT] new page caps-hub.html — size=8583
|
||||
[14:27:52] ✅ [CHANGE-DETECT] changed cartographie-screens.html — old=258098 new=1821
|
||||
[14:27:52] ✅ [CHANGE-DETECT] changed case-studies.html — old=13265 new=16851
|
||||
[14:27:52] ✅ [CHANGE-DETECT] changed cgu.html — old=8701 new=12096
|
||||
[14:27:53] ✅ [CHANGE-DETECT] changed claude-monitor.html — old=1683 new=1821
|
||||
[14:27:53] ✅ [CHANGE-DETECT] changed claw-chat.html — old=1683 new=1821
|
||||
[14:27:54] ✅ [CHANGE-DETECT] changed claw-code.html — old=1683 new=1821
|
||||
[14:27:54] ✅ [CHANGE-DETECT] changed cloudflare-hub.html — old=15165 new=18806
|
||||
[14:27:54] ✅ [CHANGE-DETECT] changed command-center.html — old=1683 new=1821
|
||||
[14:27:55] ✅ [CHANGE-DETECT] new page consultants-list.html — size=1821
|
||||
[14:27:55] ✅ [CHANGE-DETECT] new page contacts-segmentation-dashboard.html — size=1821
|
||||
[14:27:55] ✅ [CHANGE-DETECT] new page crm-audit.html — size=1821
|
||||
[14:27:56] ✅ [CHANGE-DETECT] new page crm-dashboard-live.html — size=1821
|
||||
[14:27:56] ✅ [CHANGE-DETECT] new page crm-pipeline-live.html — size=1821
|
||||
[14:27:56] ✅ [CHANGE-DETECT] changed crm.html — old=20460 new=25228
|
||||
[14:27:56] ✅ [CHANGE-DETECT] changed cron-control.html — old=1683 new=1821
|
||||
[14:27:57] ✅ [CHANGE-DETECT] changed crons-monitor.html — old=1683 new=1821
|
||||
[14:27:57] ✅ [CHANGE-DETECT] changed cyber-monitor.html — old=1683 new=1821
|
||||
[14:27:57] ✅ [CHANGE-DETECT] new page dashboards-hub.html — size=1821
|
||||
[14:27:58] ✅ [CHANGE-DETECT] changed data-deletion.html — old=2589 new=5984
|
||||
[14:27:58] ✅ [CHANGE-DETECT] new page database-dashboard-live.html — size=1821
|
||||
[14:27:58] ✅ [CHANGE-DETECT] new page decision-gmail-o365.html — size=1821
|
||||
[14:27:58] ✅ [CHANGE-DETECT] changed deepseek-hub.html — old=6405 new=9855
|
||||
[14:27:58] ✅ [CHANGE-DETECT] changed deepseek.html — old=63142 new=67672
|
||||
[14:27:59] ✅ [CHANGE-DETECT] changed deerflow-hub.html — old=4373 new=8014
|
||||
[14:27:59] ✅ [CHANGE-DETECT] new page dg-command-center.html — size=34681
|
||||
[14:27:59] ✅ [CHANGE-DETECT] changed director-center.html — old=1683 new=1821
|
||||
[14:27:59] ✅ [CHANGE-DETECT] changed director-chat.html — old=1683 new=1821
|
||||
[14:28:00] ✅ [CHANGE-DETECT] changed director.html — old=1683 new=1821
|
||||
[14:28:00] ✅ [CHANGE-DETECT] changed dmaic-tracker-NEW.html — old=5626 new=1821
|
||||
[14:28:00] ✅ [CHANGE-DETECT] changed dmaic-workbench.html — old=6798 new=1821
|
||||
[14:28:00] ✅ [CHANGE-DETECT] changed docker-hub.html — old=4398 new=8039
|
||||
[14:28:01] ✅ [CHANGE-DETECT] new page doctrine-53.html — size=1821
|
||||
[14:28:01] ✅ [CHANGE-DETECT] new page dormant-dashboard-v2.html — size=1821
|
||||
[14:28:02] ✅ [CHANGE-DETECT] new page dormant-dashboard.html — size=1821
|
||||
[14:28:02] ✅ [CHANGE-DETECT] changed droid-terminal-hidden.html — old=1683 new=1821
|
||||
[14:28:02] ✅ [CHANGE-DETECT] changed droid-terminal.html — old=107 new=1821
|
||||
[14:28:02] ✅ [CHANGE-DETECT] changed ecosysteme-ia-maroc.html — old=11412 new=14807
|
||||
[14:28:03] ✅ [CHANGE-DETECT] new page em-dashboard.html — size=1821
|
||||
[14:28:03] ✅ [CHANGE-DETECT] changed email-hub.html — old=14982 new=18623
|
||||
[14:28:03] ✅ [CHANGE-DETECT] new page enterprise-complete-v73.html — size=29606
|
||||
[14:28:03] ✅ [CHANGE-DETECT] new page enterprise-complete.html — size=35207
|
||||
[14:28:04] ✅ [CHANGE-DETECT] changed enterprise-management.html — old=1683 new=1821
|
||||
[14:28:04] ✅ [CHANGE-DETECT] changed enterprise-model.html — old=176886 new=200606
|
||||
[14:28:04] ✅ [CHANGE-DETECT] new page erp-gap-fill-offer.html — size=36827
|
||||
[14:28:04] ✅ [CHANGE-DETECT] new page erp-launchpad.html — size=33933
|
||||
[14:28:04] ✅ [CHANGE-DETECT] changed ethica-chatbot.html — old=9827 new=1821
|
||||
[14:28:05] ✅ [CHANGE-DETECT] new page ethica-country.html — size=1821
|
||||
[14:28:05] ✅ [CHANGE-DETECT] new page ethica-dashboard-live.html — size=1821
|
||||
[14:28:05] ✅ [CHANGE-DETECT] new page ethica-drill.html — size=1821
|
||||
[14:28:06] ✅ [CHANGE-DETECT] changed ethica-hcp-manager.html — old=1683 new=1821
|
||||
[14:28:06] ✅ [CHANGE-DETECT] changed ethica-hub.html — old=16892 new=20435
|
||||
[14:28:06] ✅ [CHANGE-DETECT] changed ethica-login.html — old=8595 new=1821
|
||||
[14:28:06] ✅ [CHANGE-DETECT] changed ethica-monitor.html — old=1683 new=1821
|
||||
[14:28:07] ✅ [CHANGE-DETECT] changed ethica-pipeline.html — old=1683 new=1821
|
||||
[14:28:07] Scanning APIs...
|
||||
[14:28:11] Scanning Docker...
|
||||
[14:28:11] Checking S95...
|
||||
[14:28:11] ✅ [S95-HEALTH] Sentinel reachable
|
||||
[14:28:11] ✅ [S95-HEALTH] PMTA active
|
||||
[14:28:12] ✅ [S95-HEALTH] KumoMTA active
|
||||
[14:28:12] Checking S151...
|
||||
[14:28:12] ✅ [S151-HEALTH] HTTP 200
|
||||
[14:28:12] Checking Blade...
|
||||
[14:28:12] ✅ [BLADE-HEALTH] heartbeat fresh — 0min ago, blade
|
||||
[14:28:12] Checking Paperclip...
|
||||
[14:28:12] ✅ [PAPERCLIP] service live (HTTP 200)
|
||||
[14:28:12] Checking disk...
|
||||
[14:28:12] ✅ [DISK] usage 78% — 78%
|
||||
[14:28:12] 🔍 Changes detected: 102
|
||||
[14:28:12] 📸 PHASE 2: Auto-testing pages...
|
||||
[14:28:16] ✅ [PAGE-TEST] blade-ai.html OK — body=771, 0 JS errors
|
||||
[14:28:20] ✅ [PAGE-TEST] crm.html OK — body=127, 0 JS errors
|
||||
[14:28:25] ✅ [PAGE-TEST] agents-goodjob.html OK — body=52, 0 JS errors
|
||||
[14:28:28] ✅ [PAGE-TEST] admin-saas.html OK — body=1435, 0 JS errors
|
||||
[14:28:31] ✅ [PAGE-TEST] crons-monitor.html OK — body=153, 0 JS errors
|
||||
11
patch_security_fortress.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
PATH_F="/var/www/html/api/wevia-security-fortress.php"
|
||||
# Check if already patched
|
||||
if grep -q "V88 hardened" "$PATH_F"; then
|
||||
echo "ALREADY"
|
||||
exit 0
|
||||
fi
|
||||
# Need to use sudo if root-owned
|
||||
sudo -n sh -c "chattr -i $PATH_F 2>/dev/null; sed -i '1a // V88 hardened\n@set_time_limit(30);\n@ini_set(\"memory_limit\", \"128M\");' $PATH_F; chattr +i $PATH_F 2>/dev/null"
|
||||
php8.4 -l "$PATH_F" 2>&1 | tail -1
|
||||
grep -c "V88" "$PATH_F"
|
||||
31
scan_state.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
echo "=== NR cache ==="
|
||||
stat -c "cache_date: %y" /tmp/l99-honest-cache.json 2>/dev/null
|
||||
AGE=$(($(date +%s) - $(stat -c %Y /tmp/l99-honest-cache.json 2>/dev/null || echo 0)))
|
||||
echo "cache_age: ${AGE}s"
|
||||
python3 -c "
|
||||
import json
|
||||
d=json.load(open('/tmp/l99-honest-cache.json'))
|
||||
print(f'NR: {d[\"combined\"][\"pass\"]}/{d[\"combined\"][\"total\"]} · {d[\"pct\"]}% · {d[\"sigma\"]}')
|
||||
print(f'ts: {d[\"ts\"]}')
|
||||
" 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "=== Git ==="
|
||||
cd /var/www/html && echo "dirty: $(git status --short | wc -l)"
|
||||
cd /var/www/html && git log -1 --format="head: %h %s"
|
||||
|
||||
echo ""
|
||||
echo "=== FPM ==="
|
||||
ps aux | grep -c "php-fpm: pool"
|
||||
|
||||
echo ""
|
||||
echo "=== V88 patches verify ==="
|
||||
echo "auto-heal: $(grep -c 'V88' /var/www/html/api/wevia-auto-heal.php)"
|
||||
echo "master-autoheal: $(grep -c 'V88' /var/www/html/api/wevia-master-autoheal.php)"
|
||||
echo "searxng: $(grep -c 'V88' /var/www/html/api/searxng-proxy.php)"
|
||||
echo "v83-dash-data: $(grep -c 'V88' /var/www/html/api/v83-business-kpi-dashboard-data.php)"
|
||||
|
||||
echo ""
|
||||
echo "=== L99 cron ==="
|
||||
crontab -l 2>/dev/null | grep -i l99 | head -3
|
||||
BIN
screenshots/Admin.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
screenshots/Archi3D.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/Architecture.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
screenshots/CRM.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
screenshots/Console.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/DeerFlow.png
Normal file
|
After Width: | Height: | Size: 256 KiB |
BIN
screenshots/DirChat.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/Director.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/Enterprise.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
screenshots/Fleet.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/Kuma.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
screenshots/L99Brain.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
screenshots/Langfuse.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
screenshots/Mattermost.png
Normal file
|
After Width: | Height: | Size: 322 KiB |
BIN
screenshots/Meetings.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/MiroFish.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
screenshots/OpenClaw.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/Paperclip.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
screenshots/PaperclipPg.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
screenshots/Plausible.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
screenshots/ValueStream.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/WEVADS.png
Normal file
|
After Width: | Height: | Size: 308 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 231 KiB After Width: | Height: | Size: 231 KiB |
BIN
screenshots/n8n.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 478 KiB After Width: | Height: | Size: 480 KiB |
|
Before Width: | Height: | Size: 775 KiB After Width: | Height: | Size: 776 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 141 KiB |
|
Before Width: | Height: | Size: 244 KiB After Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 650 KiB After Width: | Height: | Size: 649 KiB |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 297 KiB After Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 239 KiB After Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 232 KiB |
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 191 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 90 KiB |
97
selenium_business_test.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
V89 Selenium Business Scenario Test (headless chrome)
|
||||
Scenarios testés:
|
||||
1. WTP (weval-technology-platform.html) - page principale
|
||||
2. WEVIA Master chat
|
||||
3. CRM Bridge V68
|
||||
4. Business KPI V83
|
||||
5. Manifest endpoint
|
||||
6. 15 Depts dashboard
|
||||
"""
|
||||
import sys, os, time, json, traceback
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
|
||||
opts = Options()
|
||||
opts.add_argument("--headless=new")
|
||||
opts.add_argument("--no-sandbox")
|
||||
opts.add_argument("--disable-dev-shm-usage")
|
||||
opts.add_argument("--disable-gpu")
|
||||
opts.add_argument("--window-size=1920,1080")
|
||||
opts.add_argument("--ignore-certificate-errors")
|
||||
opts.add_argument("--disable-web-security")
|
||||
|
||||
results = {"ts": time.strftime("%Y-%m-%dT%H:%M:%S"), "scenarios": [], "pass": 0, "fail": 0}
|
||||
|
||||
def run_scenario(name, url, expected_text=None, check_title=True, timeout=12):
|
||||
"""Test a page: loads, title+body+screenshot + opt text match"""
|
||||
driver = None
|
||||
try:
|
||||
driver = webdriver.Chrome(options=opts)
|
||||
driver.set_page_load_timeout(timeout)
|
||||
t0 = time.time()
|
||||
driver.get(url)
|
||||
load_time = round(time.time() - t0, 2)
|
||||
title = driver.title
|
||||
body = driver.find_element(By.TAG_NAME, "body").text[:300]
|
||||
status = "PASS"
|
||||
detail = {"title": title, "body_preview": body[:100], "load_time_s": load_time}
|
||||
|
||||
if expected_text and expected_text.lower() not in body.lower() and expected_text.lower() not in title.lower():
|
||||
status = "WARN"
|
||||
detail["missing_text"] = expected_text
|
||||
|
||||
# Screenshot
|
||||
screenshot_path = f"/tmp/selenium_{name}.png"
|
||||
driver.save_screenshot(screenshot_path)
|
||||
detail["screenshot"] = screenshot_path
|
||||
detail["screenshot_size"] = os.path.getsize(screenshot_path)
|
||||
|
||||
results["scenarios"].append({"name": name, "url": url, "status": status, **detail})
|
||||
if status == "PASS": results["pass"] += 1
|
||||
else: results["fail"] += 1
|
||||
print(f" [{status}] {name:<30} load={load_time}s title='{title[:50]}'")
|
||||
except Exception as e:
|
||||
results["scenarios"].append({"name": name, "url": url, "status": "FAIL", "error": str(e)[:200]})
|
||||
results["fail"] += 1
|
||||
print(f" [FAIL] {name:<30} {str(e)[:100]}")
|
||||
finally:
|
||||
if driver: driver.quit()
|
||||
|
||||
print("=" * 70)
|
||||
print("V89 SELENIUM BUSINESS SCENARIOS")
|
||||
print("=" * 70)
|
||||
|
||||
scenarios = [
|
||||
("wtp_main", "https://weval-consulting.com/weval-technology-platform.html", "WEVAL"),
|
||||
("wevia_master", "https://weval-consulting.com/wevia-master.html", "WEVIA"),
|
||||
("business_kpi", "https://weval-consulting.com/business-kpi-dashboard.php", "KPI"),
|
||||
("crm_hub", "https://weval-consulting.com/crm.html", None),
|
||||
("main_site", "https://weval-consulting.com/", "WEVAL"),
|
||||
("manifest_api", "https://weval-consulting.com/api/weval-archi-manifest.php", "weval"),
|
||||
("l99_honest", "https://weval-consulting.com/api/l99-honest.php", "6sigma"),
|
||||
("depts_kpi", "https://weval-consulting.com/api/wevia-v64-departments-kpi.php", "departments"),
|
||||
]
|
||||
|
||||
for name, url, expected in scenarios:
|
||||
run_scenario(name, url, expected)
|
||||
|
||||
print()
|
||||
print("=" * 70)
|
||||
print(f"RESULTS: {results['pass']} PASS / {results['fail']} FAIL")
|
||||
print("=" * 70)
|
||||
|
||||
# Save results
|
||||
with open("/tmp/selenium_business_results.json", "w") as f:
|
||||
json.dump(results, f, indent=2)
|
||||
print(f"Saved: /tmp/selenium_business_results.json")
|
||||
|
||||
# Cleanup if ok
|
||||
total = results["pass"] + results["fail"]
|
||||
pct = round(100 * results["pass"] / total, 1) if total else 0
|
||||
print(f"Pass rate: {pct}%")
|
||||
sys.exit(0 if results["fail"] == 0 else 1)
|
||||
21
tune_fpm.py
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
path = "/etc/php/8.5/fpm/pool.d/www.conf"
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
|
||||
# Tune pm.* values - more aggressive spare servers to avoid "seems busy" warnings
|
||||
replacements = [
|
||||
(b"pm.max_children = 80", b"pm.max_children = 100"),
|
||||
(b"pm.start_servers = 20", b"pm.start_servers = 30"),
|
||||
(b"pm.min_spare_servers = 10", b"pm.min_spare_servers = 15"),
|
||||
(b"pm.max_spare_servers = 30", b"pm.max_spare_servers = 40"),
|
||||
]
|
||||
|
||||
for old, new in replacements:
|
||||
# Only replace ACTIVE lines (not comments) - we know they're now deduped
|
||||
if old in raw and b";" + old not in raw[:raw.find(old)+len(old)+1]:
|
||||
raw = raw.replace(old, new, 1)
|
||||
|
||||
with open(path, "wb") as f:
|
||||
f.write(raw)
|
||||
print("tuned")
|
||||