Files
wevads-platform/scripts/html-guardian.sh

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"