178 lines
8.8 KiB
Bash
Executable File
178 lines
8.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# ╔═══════════════════════════════════════════════════════════════╗
|
|
# ║ 🛡️ HTML GUARDIAN — Anti-Regression Engine ║
|
|
# ║ Checks: size, truncation, script integrity, theme, API ║
|
|
# ║ Auto-restores from vault gold if regression detected ║
|
|
# ║ Cron: every 10 min ║
|
|
# ╚═══════════════════════════════════════════════════════════════╝
|
|
|
|
LOG="/opt/wevads/logs/html-guardian-cron.log"
|
|
VAULT="/opt/wevads/vault"
|
|
LIVE="/opt/wevads/public"
|
|
DB="psql -U postgres -d adx_system -t -A"
|
|
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
|
FIXED=0
|
|
ISSUES=0
|
|
CHECKED=0
|
|
ALERTS=""
|
|
|
|
mkdir -p /opt/wevads/logs
|
|
|
|
log() { echo "[$TIMESTAMP] $1" >> "$LOG"; }
|
|
alert() { ALERTS="${ALERTS}\n$1"; log "ALERT: $1"; }
|
|
|
|
log "===== HTML GUARDIAN SCAN ====="
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# CHECK 1: SIZE REGRESSION (file shrunk >30% vs gold)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
for gold in "$VAULT"/*.html.gold; do
|
|
[ -f "$gold" ] || continue
|
|
fname=$(basename "$gold" .gold)
|
|
live="$LIVE/$fname"
|
|
[ -f "$live" ] || continue
|
|
|
|
CHECKED=$((CHECKED+1))
|
|
gold_size=$(wc -c < "$gold")
|
|
live_size=$(wc -c < "$live")
|
|
|
|
# Skip tiny files
|
|
[ "$gold_size" -lt 1000 ] && continue
|
|
|
|
# Calculate shrink percentage
|
|
if [ "$live_size" -lt "$((gold_size * 70 / 100))" ]; then
|
|
ISSUES=$((ISSUES+1))
|
|
alert "SIZE REGRESSION: $fname gold=${gold_size}B live=${live_size}B ($(( (gold_size - live_size) * 100 / gold_size ))% shrink)"
|
|
|
|
# Auto-restore from gold
|
|
# ALERT_MODE_DISABLED: cp "$gold" "$live"
|
|
# ALERT_MODE_DISABLED: cp "$gold" "/opt/wevads-arsenal/public/$fname" 2>/dev/null
|
|
# ALERT_MODE_DISABLED: FIXED=$((FIXED+1))
|
|
log " RESTORED $fname from vault gold"
|
|
|
|
# Log to DB
|
|
$DB -c "INSERT INTO admin.vault_guard_log (file_path, vault_path, issue_type, vault_size, live_size, action_taken) VALUES ('$live', '$gold', 'size_regression', $gold_size, $live_size, 'detected-only (analyse mode)')" 2>/dev/null
|
|
fi
|
|
done
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# CHECK 2: TRUNCATION (missing </html> or </script> unclosed)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
for f in "$LIVE"/*.html; do
|
|
fname=$(basename "$f")
|
|
size=$(wc -c < "$f")
|
|
[ "$size" -lt 5000 ] && continue
|
|
|
|
has_close_html=$(grep -c '</html>' "$f")
|
|
has_script=$(grep -c '<script' "$f")
|
|
has_close_script=$(grep -c '</script>' "$f")
|
|
|
|
# Missing closing tags
|
|
if [ "$has_close_html" -eq 0 ]; then
|
|
ISSUES=$((ISSUES+1))
|
|
gold="$VAULT/${fname}.gold"
|
|
if [ -f "$gold" ] && grep -q '</html>' "$gold"; then
|
|
# ALERT_MODE_DISABLED: cp "$gold" "$f"
|
|
# ALERT_MODE_DISABLED: cp "$gold" "/opt/wevads-arsenal/public/$fname" 2>/dev/null
|
|
# ALERT_MODE_DISABLED: FIXED=$((FIXED+1))
|
|
alert "TRUNCATED: $fname — restored from gold"
|
|
else
|
|
echo "</body></html>" >> "$f"
|
|
# ALERT_MODE_DISABLED: FIXED=$((FIXED+1))
|
|
alert "TRUNCATED: $fname — appended closing tags"
|
|
fi
|
|
fi
|
|
|
|
# Unclosed script tag = broken JS
|
|
if [ "$has_script" -gt 0 ] && [ "$has_close_script" -eq 0 ]; then
|
|
ISSUES=$((ISSUES+1))
|
|
gold="$VAULT/${fname}.gold"
|
|
if [ -f "$gold" ]; then
|
|
# ALERT_MODE_DISABLED: cp "$gold" "$f"
|
|
# ALERT_MODE_DISABLED: cp "$gold" "/opt/wevads-arsenal/public/$fname" 2>/dev/null
|
|
# ALERT_MODE_DISABLED: FIXED=$((FIXED+1))
|
|
alert "BROKEN JS: $fname — unclosed <script>, restored from gold"
|
|
else
|
|
alert "BROKEN JS: $fname — no gold available!"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# CHECK 3: CRITICAL SCREENS (must exist + min size)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
CRITICAL_SCREENS="brain-send.html warming-engine.html ceo-dashboard.html command-center.html youtube-factory.html ads-commander.html menu.html brain-central.html"
|
|
for fname in $CRITICAL_SCREENS; do
|
|
live="$LIVE/$fname"
|
|
if [ ! -f "$live" ]; then
|
|
ISSUES=$((ISSUES+1))
|
|
gold="$VAULT/${fname}.gold"
|
|
if [ -f "$gold" ]; then
|
|
# ALERT_MODE_DISABLED: cp "$gold" "$live"
|
|
# ALERT_MODE_DISABLED: cp "$gold" "/opt/wevads-arsenal/public/$fname" 2>/dev/null
|
|
# ALERT_MODE_DISABLED: FIXED=$((FIXED+1))
|
|
alert "MISSING CRITICAL: $fname — restored from gold"
|
|
else
|
|
alert "MISSING CRITICAL: $fname — NO GOLD BACKUP!"
|
|
fi
|
|
elif [ "$(wc -c < "$live")" -lt 5000 ]; then
|
|
ISSUES=$((ISSUES+1))
|
|
gold="$VAULT/${fname}.gold"
|
|
if [ -f "$gold" ] && [ "$(wc -c < "$gold")" -gt 5000 ]; then
|
|
# ALERT_MODE_DISABLED: cp "$gold" "$live"
|
|
# ALERT_MODE_DISABLED: FIXED=$((FIXED+1))
|
|
alert "CRITICAL TOO SMALL: $fname — restored from gold"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# CHECK 4: PHP SYNTAX (from original sentinel)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
for dir in /opt/wevads-arsenal/public/api /opt/wevads-arsenal/public; do
|
|
for f in "$dir"/*.php; do
|
|
[ -f "$f" ] || continue
|
|
result=$(php -l "$f" 2>&1)
|
|
if echo "$result" | grep -q 'Parse error\|Fatal'; then
|
|
ISSUES=$((ISSUES+1))
|
|
fname=$(basename "$f")
|
|
goldname=$(echo "$f" | sed 's|/|__|g' | sed 's|^__||').gold
|
|
gold="$VAULT/$goldname"
|
|
if [ -f "$gold" ]; then
|
|
# ALERT_MODE_DISABLED: cp "$gold" "$f"
|
|
# ALERT_MODE_DISABLED: FIXED=$((FIXED+1))
|
|
alert "PHP BROKEN: $fname — restored from gold"
|
|
else
|
|
alert "PHP BROKEN: $fname — no gold available!"
|
|
fi
|
|
fi
|
|
done
|
|
done
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# CHECK 5: MD5 INTEGRITY (detect any unauthorized changes)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
CHECKSUM_FILE="/opt/wevads/vault/checksums.md5"
|
|
if [ -f "$CHECKSUM_FILE" ]; then
|
|
CHANGED_GOLD=$(cd "$VAULT" && md5sum -c "$CHECKSUM_FILE" 2>/dev/null | grep -c "FAILED")
|
|
if [ "$CHANGED_GOLD" -gt 0 ]; then
|
|
alert "VAULT CORRUPTION: $CHANGED_GOLD gold files have been modified!"
|
|
ISSUES=$((ISSUES+$CHANGED_GOLD))
|
|
fi
|
|
fi
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# REPORT
|
|
# ═══════════════════════════════════════════════════════════════
|
|
log "RESULT: checked=$CHECKED issues=$ISSUES fixed=$FIXED"
|
|
|
|
# Write to DB
|
|
$DB -c "INSERT INTO admin.sentinel_scans (scan_type, files_checked, issues_found, issues_fixed, scan_details, created_at) VALUES ('html_guardian', $CHECKED, $ISSUES, $FIXED, '$(echo -e "$ALERTS" | head -20 | sed "s/'/''/g")', NOW())" 2>/dev/null
|
|
|
|
# Write status file for API
|
|
cat > /opt/wevads/logs/html-guardian-status-new.json << JSONEOF
|
|
{"last_scan":"$TIMESTAMP","checked":$CHECKED,"issues":$ISSUES,"fixed":$FIXED,"status":"$([ $ISSUES -eq 0 ] && echo 'healthy' || echo 'repaired')"}
|
|
JSONEOF
|
|
|
|
echo "HTML Guardian: checked=$CHECKED issues=$ISSUES fixed=$FIXED"
|