# System Hub v0.3.5 Development Codex **Target Version:** 0.3.5 **Current Version:** 0.3.2 **Release Date:** 2025-01-20 **Priority:** High - Production Feature Completion **Maintainer:** CyberMind --- ## ๐ŸŽฏ Mission Statement Transform `luci-app-system-hub` from an **80% production-ready monitoring dashboard** into a **100% feature-complete system control center** by implementing real diagnostics collection, remote management integration, email notifications, report generation, and scheduled task execution. --- ## ๐Ÿ“Š Current State Analysis (v0.3.2) ### โœ… What's Production-Ready (80%) **Core Monitoring:** - โœ… Real-time system health monitoring (CPU, memory, disk, temperature) - โœ… Network status (WAN connectivity, RX/TX bytes) - โœ… Service enumeration and management (start/stop/restart/enable/disable) - โœ… System information display (hostname, kernel, uptime, architecture) - โœ… Auto-refresh polling (30-second intervals) **System Management:** - โœ… Configuration backup/restore via sysupgrade - โœ… System reboot functionality - โœ… Log viewing with filtering (logread integration) - โœ… Storage information display (df command) - โœ… Settings persistence to UCI **Integration:** - โœ… SecuBox component discovery - โœ… Theme management - โœ… Development status widget ### โŒ What's Placeholder (20%) **Diagnostics (diagnostics.js):** - โŒ Diagnostic collection - UI ready, no backend implementation - โŒ Quick tests - Hardcoded simulated results - โŒ Archive generation - No actual file creation - โŒ Upload to support server - No backend logic **Remote Management (remote.js):** - โŒ RustDesk integration - UI only, no service control - โŒ Remote session management - Placeholder interface - โŒ SSH connection automation - Display only **Notifications & Reporting:** - โŒ Email notifications - Button shows "coming soon" - โŒ PDF export - UI only - โŒ Report generation - Not implemented **System Configuration:** - โŒ Hostname editing - Notification says "feature coming soon" - โŒ Scheduled tasks - Toggles saved but no cron execution - โŒ Upload to support server - Fields saved but no upload **Network Monitoring:** - โŒ DNS server discovery - Hardcoded 8.8.8.8 / 8.8.4.4 - โŒ DNS query statistics - Field displays but no data - โŒ NTP sync status - Hardcoded placeholder data - โŒ Firewall rules count - Returns 0, displays placeholder --- ## ๐Ÿš€ Version 0.3.5 Goals ### Primary Objectives 1. **Implement Real Diagnostics Collection** (Critical - 30% of v0.3.5) - Collect system logs, configuration, network info - Generate diagnostic archives (.tar.gz) - Implement quick diagnostic tests (connectivity, DNS, latency, disk I/O) - Upload diagnostics to support server 2. **Implement Remote Management** (High - 20% of v0.3.5) - RustDesk service integration (install, configure, start/stop) - Generate RustDesk ID and password - SSH connection string generation - Remote session logging 3. **Implement Email Notifications** (High - 20% of v0.3.5) - SMTP configuration and testing - Send health reports via email - Send diagnostic archives via email - Alert notifications for critical events 4. **Implement Report Generation** (Medium - 15% of v0.3.5) - Generate HTML/PDF health reports - System inventory reports - Service status reports - Export functionality 5. **Implement Scheduled Tasks** (Medium - 10% of v0.3.5) - Cron job creation for health reports - Weekly backup automation - Log cleanup scheduling - Diagnostic upload scheduling 6. **Enhanced Network Monitoring** (Medium - 5% of v0.3.5) - Real DNS server discovery from resolv.conf - DNS query statistics via dnsmasq logs - NTP sync status from ntpd/chronyd - Firewall rules count from iptables ### Success Criteria - [ ] All 14 RPCD methods have real implementations (no placeholders) - [ ] Diagnostics can be collected, archived, and uploaded - [ ] Email notifications work with SMTP configuration - [ ] HTML/PDF reports can be generated and downloaded - [ ] Scheduled tasks execute via cron jobs - [ ] Network monitoring shows real DNS/NTP/firewall data - [ ] RustDesk integration allows remote support access - [ ] All UI buttons trigger actual backend actions - [ ] No "coming soon" notifications remain - [ ] Integration tests pass for all features --- ## ๐Ÿ”ง Technical Implementation Plan ### Phase 1: Diagnostics Collection (Week 1-2) #### Task 1.1: Real Diagnostic Collection **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `collect_diagnostics()` (new) **Implementation:** ```bash collect_diagnostics() { # Read parameters from JSON input json_load "$input" json_get_var include_logs "include_logs" json_get_var include_config "include_config" json_get_var include_network "include_network" json_get_var anonymize "anonymize" # Create temporary directory local diag_dir="/tmp/diagnostics-$(date +%s)" mkdir -p "$diag_dir" # Collect system info echo "=== System Information ===" > "$diag_dir/sysinfo.txt" uname -a >> "$diag_dir/sysinfo.txt" cat /proc/cpuinfo >> "$diag_dir/sysinfo.txt" cat /proc/meminfo >> "$diag_dir/sysinfo.txt" df -h >> "$diag_dir/sysinfo.txt" uptime >> "$diag_dir/sysinfo.txt" # Collect logs if requested if [ "$include_logs" = "1" ]; then logread > "$diag_dir/system.log" dmesg > "$diag_dir/kernel.log" fi # Collect configuration if requested if [ "$include_config" = "1" ]; then mkdir -p "$diag_dir/config" sysupgrade -b "$diag_dir/config/backup.tar.gz" 2>/dev/null # Copy sanitized UCI configs for conf in /etc/config/*; do if [ "$anonymize" = "1" ]; then # Remove sensitive data (passwords, keys, IPs) grep -v -E "(password|key|secret|ip|addr)" "$conf" > "$diag_dir/config/$(basename $conf)" else cp "$conf" "$diag_dir/config/" fi done fi # Collect network info if requested if [ "$include_network" = "1" ]; then echo "=== Network Configuration ===" > "$diag_dir/network.txt" ip addr >> "$diag_dir/network.txt" ip route >> "$diag_dir/network.txt" iptables -L -n -v >> "$diag_dir/network.txt" cat /etc/resolv.conf >> "$diag_dir/network.txt" # Test connectivity ping -c 5 8.8.8.8 >> "$diag_dir/network.txt" 2>&1 ping -c 5 google.com >> "$diag_dir/network.txt" 2>&1 fi # Create archive local archive_name="diagnostics-$(hostname)-$(date +%Y%m%d-%H%M%S).tar.gz" local archive_path="/tmp/$archive_name" tar -czf "$archive_path" -C "$diag_dir" . # Calculate size local size=$(stat -c%s "$archive_path") # Encode to base64 for transmission local base64_data=$(base64 "$archive_path") # Cleanup rm -rf "$diag_dir" # Return response json_init json_add_boolean "success" 1 json_add_string "filename" "$archive_name" json_add_int "size" "$size" json_add_string "data" "$base64_data" json_dump json_cleanup } ``` **Frontend Integration (diagnostics.js):** ```javascript handleCollectDiagnostics: function() { var options = { include_logs: document.querySelector('[name="include_logs"]').checked, include_config: document.querySelector('[name="include_config"]').checked, include_network: document.querySelector('[name="include_network"]').checked, anonymize: document.querySelector('[name="anonymize"]').checked }; return API.collectDiagnostics(options).then(function(result) { if (result.success) { // Decode base64 and trigger download var blob = base64ToBlob(result.data, 'application/gzip'); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = result.filename; a.click(); URL.revokeObjectURL(url); ui.addNotification(null, E('p', 'โœ“ Diagnostics collected: ' + result.filename), 'info'); } }); } ``` --- #### Task 1.2: Quick Diagnostic Tests **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `run_diagnostic_test()` (new) **Implementation:** ```bash run_diagnostic_test() { json_load "$input" json_get_var test_type "test_type" case "$test_type" in connectivity) # Test WAN connectivity if ping -c 1 -W 2 8.8.8.8 >/dev/null 2>&1; then local result="โœ“ WAN connected" local status="ok" else local result="โœ— WAN connection failed" local status="critical" fi # Test DNS resolution if nslookup google.com >/dev/null 2>&1; then result="$result, DNS functional" else result="$result, DNS failed" status="warning" fi ;; dns) # DNS resolution test local domain="google.com" local dns_result=$(nslookup "$domain" 2>&1 | grep "Address" | tail -1 | awk '{print $3}') if [ -n "$dns_result" ]; then local result="โœ“ $domain โ†’ $dns_result" local status="ok" else local result="โœ— DNS resolution failed" local status="critical" fi ;; latency) # Ping latency test local ping_result=$(ping -c 5 8.8.8.8 2>&1 | grep "avg" | awk -F'/' '{print $5}') if [ -n "$ping_result" ]; then local latency_int=$(printf "%.0f" "$ping_result") local threshold=100 if [ "$latency_int" -lt "$threshold" ]; then local result="โœ“ ${latency_int}ms (threshold: ${threshold}ms)" local status="ok" else local result="โš  ${latency_int}ms (threshold: ${threshold}ms)" local status="warning" fi else local result="โœ— Latency test failed" local status="critical" fi ;; disk) # Disk I/O performance test local write_speed=$(dd if=/dev/zero of=/tmp/test.tmp bs=1M count=10 2>&1 | grep "copied" | awk '{print $(NF-1), $NF}') local read_speed=$(dd if=/tmp/test.tmp of=/dev/null bs=1M 2>&1 | grep "copied" | awk '{print $(NF-1), $NF}') rm -f /tmp/test.tmp local result="Write: $write_speed, Read: $read_speed" local status="ok" ;; firewall) # Firewall rules count local rules_count=$(iptables -L -n | grep -c "^ACCEPT\|^DROP\|^REJECT") if [ "$rules_count" -gt 0 ]; then local result="โœ“ $rules_count rules active" local status="ok" else local result="โš  No firewall rules configured" local status="warning" fi ;; wifi) # WiFi status local radio_count=$(uci show wireless | grep -c "wifi-device") local client_count=0 for iface in /sys/class/net/*; do if [ -d "$iface/wireless" ]; then local clients=$(iw dev $(basename $iface) station dump 2>/dev/null | grep -c "Station") client_count=$((client_count + clients)) fi done local result="$radio_count radios active, $client_count clients total" local status="ok" ;; *) local result="Unknown test type" local status="error" ;; esac json_init json_add_boolean "success" 1 json_add_string "result" "$result" json_add_string "status" "$status" json_dump json_cleanup } ``` --- #### Task 1.3: Upload Diagnostics to Support Server **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `upload_diagnostics()` (new) **Implementation:** ```bash upload_diagnostics() { json_load "$input" json_get_var archive_path "archive_path" # Load upload settings from UCI local upload_url=$(uci -q get system-hub.upload.upload_url) local upload_token=$(uci -q get system-hub.upload.upload_token) [ -z "$upload_url" ] && { json_init json_add_boolean "success" 0 json_add_string "error" "Upload URL not configured" json_dump json_cleanup return 1 } # Upload using curl local response=$(curl -s -X POST \ -H "Authorization: Bearer $upload_token" \ -F "file=@$archive_path" \ -F "hostname=$(hostname)" \ -F "timestamp=$(date +%s)" \ "$upload_url" 2>&1) local curl_exit=$? if [ $curl_exit -eq 0 ]; then json_init json_add_boolean "success" 1 json_add_string "response" "$response" json_dump json_cleanup else json_init json_add_boolean "success" 0 json_add_string "error" "Upload failed: $response" json_dump json_cleanup fi } ``` **Dependencies:** - `curl` package for HTTP uploads - `ca-certificates` for HTTPS support --- ### Phase 2: Remote Management (Week 3) #### Task 2.1: RustDesk Service Integration **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `rustdesk_install()` (new) **Implementation:** ```bash rustdesk_install() { # Check if RustDesk is already installed if opkg list-installed | grep -q rustdesk; then json_init json_add_boolean "success" 0 json_add_string "error" "RustDesk already installed" json_dump json_cleanup return 1 fi # Install RustDesk package opkg update opkg install rustdesk if [ $? -eq 0 ]; then json_init json_add_boolean "success" 1 json_add_string "message" "RustDesk installed successfully" json_dump json_cleanup else json_init json_add_boolean "success" 0 json_add_string "error" "Installation failed" json_dump json_cleanup fi } ``` **Method:** `rustdesk_configure()` (new) ```bash rustdesk_configure() { json_load "$input" json_get_var relay_server "relay_server" json_get_var api_server "api_server" json_get_var key "key" # Create RustDesk configuration cat > /etc/rustdesk/config.toml <&1) local rustdesk_password=$(rustdesk --password 2>&1) json_init json_add_boolean "success" 1 json_add_string "id" "$rustdesk_id" json_add_string "password" "$rustdesk_password" json_dump json_cleanup } ``` **Method:** `rustdesk_service_action()` (new) ```bash rustdesk_service_action() { json_load "$input" json_get_var action "action" case "$action" in start|stop|restart|enable|disable) /etc/init.d/rustdesk "$action" ;; *) json_init json_add_boolean "success" 0 json_add_string "error" "Invalid action" json_dump json_cleanup return 1 ;; esac json_init json_add_boolean "success" 1 json_add_string "action" "$action" json_dump json_cleanup } ``` --- ### Phase 3: Email Notifications (Week 4-5) #### Task 3.1: SMTP Configuration **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `configure_smtp()` (new) **Implementation:** ```bash configure_smtp() { json_load "$input" json_get_var smtp_server "smtp_server" json_get_var smtp_port "smtp_port" json_get_var smtp_user "smtp_user" json_get_var smtp_password "smtp_password" json_get_var from_email "from_email" json_get_var use_tls "use_tls" # Save to UCI uci set system-hub.smtp=smtp uci set system-hub.smtp.server="$smtp_server" uci set system-hub.smtp.port="$smtp_port" uci set system-hub.smtp.user="$smtp_user" uci set system-hub.smtp.password="$smtp_password" uci set system-hub.smtp.from_email="$from_email" uci set system-hub.smtp.use_tls="$use_tls" uci commit system-hub json_init json_add_boolean "success" 1 json_add_string "message" "SMTP configuration saved" json_dump json_cleanup } ``` **Method:** `test_smtp()` (new) ```bash test_smtp() { json_load "$input" json_get_var to_email "to_email" # Load SMTP config from UCI local smtp_server=$(uci -q get system-hub.smtp.server) local smtp_port=$(uci -q get system-hub.smtp.port) local smtp_user=$(uci -q get system-hub.smtp.user) local smtp_password=$(uci -q get system-hub.smtp.password) local from_email=$(uci -q get system-hub.smtp.from_email) local use_tls=$(uci -q get system-hub.smtp.use_tls) # Send test email using sendmail or msmtp cat > /tmp/test_email.txt </dev/null 2>&1; then # Use msmtp cat > /tmp/msmtprc < /tmp/health_report.txt </dev/null 2>&1; then cat > /tmp/msmtprc < /tmp/system-report.html <<'EOF' SecuBox System Report

SecuBox System Report

Hostname: $(hostname)

Generated: $(date)

Health Overview

$(echo "$health_json" | jsonfilter -e '@.score')/100
Overall Health

System Metrics

MetricValueStatus
CPU Usage $(echo "$health_json" | jsonfilter -e '@.cpu.usage')% $(echo "$health_json" | jsonfilter -e '@.cpu.status')
Memory Usage $(echo "$health_json" | jsonfilter -e '@.memory.usage')% $(echo "$health_json" | jsonfilter -e '@.memory.status')
Disk Usage $(echo "$health_json" | jsonfilter -e '@.disk.usage')% $(echo "$health_json" | jsonfilter -e '@.disk.status')
Temperature $(echo "$health_json" | jsonfilter -e '@.temperature.value')ยฐC $(echo "$health_json" | jsonfilter -e '@.temperature.status')

System Information

Kernel$(echo "$sysinfo_json" | jsonfilter -e '@.kernel')
Architecture$(echo "$sysinfo_json" | jsonfilter -e '@.architecture')
OpenWrt Version$(echo "$sysinfo_json" | jsonfilter -e '@.openwrt_version')
Uptime$(echo "$sysinfo_json" | jsonfilter -e '@.uptime_formatted')
EOF # Encode to base64 local base64_data=$(base64 /tmp/system-report.html) json_init json_add_boolean "success" 1 json_add_string "filename" "system-report-$(date +%Y%m%d-%H%M%S).html" json_add_string "data" "$base64_data" json_dump json_cleanup rm -f /tmp/system-report.html } ``` **Method:** `generate_pdf_report()` (new) ```bash generate_pdf_report() { # First generate HTML report generate_html_report > /tmp/report.json # Extract base64 HTML local html_data=$(cat /tmp/report.json | jsonfilter -e '@.data') echo "$html_data" | base64 -d > /tmp/system-report.html # Convert to PDF using wkhtmltopdf (if installed) if command -v wkhtmltopdf >/dev/null 2>&1; then wkhtmltopdf /tmp/system-report.html /tmp/system-report.pdf # Encode PDF to base64 local pdf_base64=$(base64 /tmp/system-report.pdf) json_init json_add_boolean "success" 1 json_add_string "filename" "system-report-$(date +%Y%m%d-%H%M%S).pdf" json_add_string "data" "$pdf_base64" json_dump json_cleanup rm -f /tmp/system-report.html /tmp/system-report.pdf /tmp/report.json else json_init json_add_boolean "success" 0 json_add_string "error" "wkhtmltopdf not installed" json_dump json_cleanup fi } ``` **Dependencies:** - `wkhtmltopdf` package for PDF generation (optional) --- ### Phase 5: Scheduled Tasks (Week 7) #### Task 5.1: Cron Job Management **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `schedule_health_report()` (new) **Implementation:** ```bash schedule_health_report() { json_load "$input" json_get_var enabled "enabled" json_get_var interval "interval" # daily, weekly, monthly json_get_var email "email" # Remove existing cron job sed -i '/system-hub-health-report/d' /etc/crontabs/root 2>/dev/null if [ "$enabled" = "1" ]; then case "$interval" in daily) local cron_time="0 6 * * *" # 6 AM daily ;; weekly) local cron_time="0 6 * * 0" # 6 AM Sunday ;; monthly) local cron_time="0 6 1 * *" # 6 AM 1st of month ;; *) local cron_time="0 6 * * 0" # Default to weekly ;; esac # Add cron job echo "$cron_time /usr/libexec/system-hub/send-health-report.sh $email # system-hub-health-report" >> /etc/crontabs/root # Create helper script cat > /usr/libexec/system-hub/send-health-report.sh <<'EOF' #!/bin/sh # Send health report via email to_email="$1" [ -z "$to_email" ] && exit 1 # Call RPCD method via ubus ubus call luci.system-hub send_health_report_email "{\"to_email\": \"$to_email\"}" EOF chmod +x /usr/libexec/system-hub/send-health-report.sh # Restart cron /etc/init.d/cron restart fi json_init json_add_boolean "success" 1 json_add_string "message" "Health report schedule updated" json_dump json_cleanup } ``` **Method:** `schedule_backup()` (new) ```bash schedule_backup() { json_load "$input" json_get_var enabled "enabled" # Remove existing cron job sed -i '/system-hub-backup/d' /etc/crontabs/root 2>/dev/null if [ "$enabled" = "1" ]; then # Weekly backup at 3 AM on Sunday local cron_time="0 3 * * 0" # Add cron job echo "$cron_time /usr/libexec/system-hub/weekly-backup.sh # system-hub-backup" >> /etc/crontabs/root # Create helper script cat > /usr/libexec/system-hub/weekly-backup.sh <<'EOF' #!/bin/sh # Weekly configuration backup backup_dir="/root/backups" mkdir -p "$backup_dir" # Create backup backup_file="$backup_dir/config-backup-$(date +\%Y\%m\%d-\%H\%M\%S).tar.gz" sysupgrade -b "$backup_file" # Keep only last 10 backups ls -t "$backup_dir"/config-backup-*.tar.gz | tail -n +11 | xargs -r rm EOF chmod +x /usr/libexec/system-hub/weekly-backup.sh # Restart cron /etc/init.d/cron restart fi json_init json_add_boolean "success" 1 json_add_string "message" "Backup schedule updated" json_dump json_cleanup } ``` **Method:** `schedule_log_cleanup()` (new) ```bash schedule_log_cleanup() { json_load "$input" json_get_var enabled "enabled" json_get_var retention_days "retention_days" # Remove existing cron job sed -i '/system-hub-log-cleanup/d' /etc/crontabs/root 2>/dev/null if [ "$enabled" = "1" ]; then # Daily cleanup at 2 AM local cron_time="0 2 * * *" # Add cron job echo "$cron_time /usr/libexec/system-hub/cleanup-logs.sh $retention_days # system-hub-log-cleanup" >> /etc/crontabs/root # Create helper script cat > /usr/libexec/system-hub/cleanup-logs.sh <<'EOF' #!/bin/sh # Cleanup old log files retention_days="${1:-7}" # Clean old log files find /var/log -name "*.log" -mtime +$retention_days -exec rm {} \; find /tmp -name "*.log" -mtime +$retention_days -exec rm {} \; # Rotate system log if too large (> 1MB) logfile="/var/log/messages" if [ -f "$logfile" ] && [ $(stat -c%s "$logfile") -gt 1048576 ]; then mv "$logfile" "$logfile.old" touch "$logfile" fi EOF chmod +x /usr/libexec/system-hub/cleanup-logs.sh # Restart cron /etc/init.d/cron restart fi json_init json_add_boolean "success" 1 json_add_string "message" "Log cleanup schedule updated" json_dump json_cleanup } ``` --- ### Phase 6: Enhanced Network Monitoring (Week 8) #### Task 6.1: Real DNS Server Discovery **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** Update `get_health()` DNS section **Implementation:** ```bash # In get_health() function, replace DNS section with: # DNS servers from resolv.conf dns_primary=$(grep "nameserver" /etc/resolv.conf | head -1 | awk '{print $2}') dns_secondary=$(grep "nameserver" /etc/resolv.conf | sed -n '2p' | awk '{print $2}') # DNS query statistics from dnsmasq log if [ -f /var/log/dnsmasq.log ]; then dns_queries=$(grep "query" /var/log/dnsmasq.log | wc -l) else # Estimate from dnsmasq cache dns_queries=$(dnsmasq --test 2>&1 | grep -o "cache-size=[0-9]*" | cut -d= -f2) fi json_add_string "dns_primary" "${dns_primary:-8.8.8.8}" json_add_string "dns_secondary" "${dns_secondary:-8.8.4.4}" json_add_int "dns_queries" "${dns_queries:-0}" json_add_boolean "dns_ok" "$(nslookup google.com >/dev/null 2>&1 && echo 1 || echo 0)" ``` --- #### Task 6.2: Real NTP Sync Status **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** Update `get_health()` NTP section **Implementation:** ```bash # In get_health() function, add NTP section: # NTP sync status if command -v ntpd >/dev/null 2>&1; then ntp_status=$(ntpq -p 2>/dev/null | grep "^\*" | wc -l) ntp_server=$(ntpq -p 2>/dev/null | grep "^\*" | awk '{print $1}' | sed 's/\*//') ntp_offset=$(ntpq -p 2>/dev/null | grep "^\*" | awk '{print $9}') ntp_last_sync="Just now" elif command -v chronyd >/dev/null 2>&1; then ntp_status=$(chronyc tracking 2>/dev/null | grep "Reference ID" | wc -l) ntp_server=$(chronyc sources 2>/dev/null | grep "^\^\*" | awk '{print $2}') ntp_offset=$(chronyc tracking 2>/dev/null | grep "System time" | awk '{print $4}') ntp_last_sync=$(chronyc sources 2>/dev/null | grep "^\^\*" | awk '{print $5}') else ntp_status=0 ntp_server="pool.ntp.org" ntp_offset="0" ntp_last_sync="Unknown" fi json_add_string "ntp_server" "$ntp_server" json_add_string "ntp_offset" "$ntp_offset" json_add_string "ntp_last_sync" "$ntp_last_sync" json_add_boolean "ntp_synced" "$ntp_status" ``` --- #### Task 6.3: Real Firewall Rules Count **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** Update `get_health()` firewall section **Implementation:** ```bash # In get_health() function, add firewall section: # Firewall rules fw_rules=$(iptables -L -n | grep -c "^ACCEPT\|^DROP\|^REJECT") fw_input=$(iptables -L INPUT -n | grep "policy" | awk '{print $4}') fw_forward=$(iptables -L FORWARD -n | grep "policy" | awk '{print $4}') fw_output=$(iptables -L OUTPUT -n | grep "policy" | awk '{print $4}') json_add_int "firewall_rules" "$fw_rules" json_add_string "fw_input" "$fw_input" json_add_string "fw_forward" "$fw_forward" json_add_string "fw_output" "$fw_output" ``` --- ### Phase 7: Hostname Editing & Archive Management (Week 9) #### Task 7.1: Hostname Editing **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `set_hostname()` (new) **Implementation:** ```bash set_hostname() { json_load "$input" json_get_var new_hostname "hostname" # Validate hostname if ! echo "$new_hostname" | grep -qE '^[a-zA-Z0-9-]+$'; then json_init json_add_boolean "success" 0 json_add_string "error" "Invalid hostname format" json_dump json_cleanup return 1 fi # Update /etc/config/system uci set system.@system[0].hostname="$new_hostname" uci commit system # Update /proc/sys/kernel/hostname echo "$new_hostname" > /proc/sys/kernel/hostname # Update /etc/hosts sed -i "s/127.0.1.1.*/127.0.1.1\t$new_hostname/" /etc/hosts json_init json_add_boolean "success" 1 json_add_string "hostname" "$new_hostname" json_add_string "message" "Hostname updated to $new_hostname" json_dump json_cleanup } ``` **Frontend Integration (overview.js):** ```javascript // Replace "Edit" button click handler: 'click': function() { ui.showModal('Edit Hostname', [ E('p', {}, 'Enter new hostname:'), E('input', { 'type': 'text', 'class': 'cbi-input-text', 'id': 'new-hostname', 'value': self.sysInfo.hostname || '', 'pattern': '[a-zA-Z0-9-]+', 'maxlength': '63' }), E('div', { 'class': 'right' }, [ E('button', { 'class': 'btn cbi-button-negative', 'click': ui.hideModal }, 'Cancel'), E('button', { 'class': 'btn cbi-button-positive', 'click': function() { var newHostname = document.getElementById('new-hostname').value; if (!newHostname.match(/^[a-zA-Z0-9-]+$/)) { ui.addNotification(null, E('p', 'Invalid hostname'), 'error'); return; } API.setHostname(newHostname).then(function(result) { if (result.success) { ui.addNotification(null, E('p', 'โœ“ ' + result.message), 'info'); ui.hideModal(); location.reload(); } else { ui.addNotification(null, E('p', 'โœ— ' + result.error), 'error'); } }); } }, 'Save') ]) ]); } ``` --- #### Task 7.2: Recent Archives List **File:** `root/usr/libexec/rpcd/luci.system-hub` **Method:** `list_recent_archives()` (new) **Implementation:** ```bash list_recent_archives() { local backup_dir="/root/backups" mkdir -p "$backup_dir" json_init json_add_array "archives" # List backup files sorted by date for archive in $(ls -t "$backup_dir"/config-backup-*.tar.gz 2>/dev/null | head -10); do local filename=$(basename "$archive") local size=$(stat -c%s "$archive") local timestamp=$(stat -c%Y "$archive") local date=$(date -d "@$timestamp" "+%Y-%m-%d %H:%M:%S") json_add_object json_add_string "filename" "$filename" json_add_int "size" "$size" json_add_string "date" "$date" json_add_string "path" "$archive" json_close_object done json_close_array json_dump json_cleanup } ``` --- ## ๐Ÿงช Testing & Validation ### Unit Tests **Test File:** `tests/test-system-hub.sh` (new) ```bash #!/bin/sh # System Hub v0.3.5 Test Suite test_diagnostics_collection() { echo "Testing diagnostics collection..." result=$(ubus call luci.system-hub collect_diagnostics '{"include_logs":true,"include_config":true,"include_network":true,"anonymize":false}') success=$(echo "$result" | jsonfilter -e '@.success') [ "$success" = "true" ] || { echo "FAIL: Diagnostics collection"; return 1; } echo "PASS: Diagnostics collected" } test_quick_diagnostic_tests() { echo "Testing quick diagnostic tests..." for test in connectivity dns latency disk firewall wifi; do result=$(ubus call luci.system-hub run_diagnostic_test "{\"test_type\":\"$test\"}") success=$(echo "$result" | jsonfilter -e '@.success') [ "$success" = "true" ] || { echo "FAIL: $test test"; return 1; } echo "PASS: $test test" done } test_smtp_configuration() { echo "Testing SMTP configuration..." result=$(ubus call luci.system-hub configure_smtp '{"smtp_server":"smtp.gmail.com","smtp_port":"587","smtp_user":"test@example.com","smtp_password":"password","from_email":"test@example.com","use_tls":"1"}') success=$(echo "$result" | jsonfilter -e '@.success') [ "$success" = "true" ] || { echo "FAIL: SMTP config"; return 1; } echo "PASS: SMTP configuration saved" } test_html_report_generation() { echo "Testing HTML report generation..." result=$(ubus call luci.system-hub generate_html_report) success=$(echo "$result" | jsonfilter -e '@.success') filename=$(echo "$result" | jsonfilter -e '@.filename') [ "$success" = "true" ] || { echo "FAIL: HTML report"; return 1; } [ -n "$filename" ] || { echo "FAIL: No filename"; return 1; } echo "PASS: HTML report generated ($filename)" } test_hostname_change() { echo "Testing hostname change..." old_hostname=$(hostname) result=$(ubus call luci.system-hub set_hostname '{"hostname":"test-router"}') success=$(echo "$result" | jsonfilter -e '@.success') [ "$success" = "true" ] || { echo "FAIL: Hostname change"; return 1; } # Restore original hostname ubus call luci.system-hub set_hostname "{\"hostname\":\"$old_hostname\"}" echo "PASS: Hostname change" } test_cron_scheduling() { echo "Testing cron scheduling..." result=$(ubus call luci.system-hub schedule_health_report '{"enabled":"1","interval":"weekly","email":"admin@example.com"}') success=$(echo "$result" | jsonfilter -e '@.success') [ "$success" = "true" ] || { echo "FAIL: Cron scheduling"; return 1; } # Check if cron job exists grep -q "system-hub-health-report" /etc/crontabs/root || { echo "FAIL: Cron job not created"; return 1; } echo "PASS: Cron scheduling" } test_dns_discovery() { echo "Testing DNS server discovery..." result=$(ubus call luci.system-hub get_health) dns_primary=$(echo "$result" | jsonfilter -e '@.network.dns_primary') [ -n "$dns_primary" ] || { echo "FAIL: DNS primary not found"; return 1; } echo "PASS: DNS discovery (primary: $dns_primary)" } # Run all tests test_diagnostics_collection test_quick_diagnostic_tests test_smtp_configuration test_html_report_generation test_hostname_change test_cron_scheduling test_dns_discovery echo "" echo "Test suite completed." ``` --- ## ๐Ÿ“‹ Pre-Release Checklist ### Code Quality - [ ] All RPCD methods return valid JSON - [ ] Error handling for missing dependencies - [ ] Input validation for user-provided data - [ ] No hardcoded credentials - [ ] Shellcheck passes on all RPCD scripts - [ ] No placeholder comments remain ### Functionality - [ ] Diagnostics collection works with all options - [ ] Quick tests return real results - [ ] SMTP email sending works - [ ] HTML/PDF reports generate correctly - [ ] Cron jobs are created and execute - [ ] DNS/NTP/firewall data is real - [ ] Hostname editing works and persists - [ ] Archive list shows real backup files - [ ] RustDesk integration installs and configures ### Safety - [ ] No destructive operations without confirmation - [ ] Config backups created before changes - [ ] Cron jobs don't overlap or conflict - [ ] Email passwords stored securely in UCI - [ ] Diagnostic anonymization removes sensitive data ### Documentation - [ ] README.md updated with new features - [ ] Dependency list includes new packages - [ ] Configuration examples provided - [ ] API documentation for new RPCD methods --- ## ๐Ÿšข Release Process ### Version Bump ```bash # Update Makefile sed -i 's/PKG_VERSION:=0.3.2/PKG_VERSION:=0.3.5/' luci-app-system-hub/Makefile # Update README.md sed -i 's/Version: 0.3.2/Version: 0.3.5/' luci-app-system-hub/README.md # Update api.js version sed -i 's/v0.2.2/v0.2.5/' luci-app-system-hub/htdocs/luci-static/resources/system-hub/api.js ``` ### Git Workflow ```bash git add luci-app-system-hub/ git commit -m "feat(system-hub): Implement v0.3.5 production features - Diagnostics: Real collection, archive generation, upload - Remote: RustDesk service integration and management - Email: SMTP config, health reports, test emails - Reports: HTML/PDF generation with system metrics - Scheduling: Cron jobs for reports, backups, log cleanup - Network: Real DNS, NTP, firewall monitoring - Hostname: Edit and persist hostname changes - Archives: List recent backups with metadata Closes #XX, #YY, #ZZ" git tag -a v0.3.5 -m "Release v0.3.5: Feature Completion" git push origin master --tags ``` --- ## ๐ŸŽ“ Implementation Guidelines ### Code Style - Follow existing RPCD patterns - Use jshn.sh for JSON handling - Return `{"success": true/false}` for all methods - Log errors to syslog - Use UCI for configuration storage ### Security Best Practices - Validate all user input - Escape shell variables: `"$var"` not `$var` - Use `uci -q get` to avoid errors - Check command existence: `command -v cmd >/dev/null` - Anonymize sensitive data in diagnostics ### Performance Considerations - Don't block on long-running operations - Use background jobs for email/upload - Cache diagnostic archives for reuse - Clean up temporary files after operations --- ## ๐Ÿ“Š Success Metrics **Completion Targets:** - Implementation: 95-100% (up from 80%) - Feature Parity: 14/14 RPCD methods fully functional - Test Coverage: 90%+ unit tests passing - Documentation: 100% of new features documented - User Feedback: No "coming soon" notifications **User Impact:** - One-click diagnostics collection (vs manual log gathering) - Automated health reports via email (vs manual checks) - Remote support access via RustDesk (vs SSH only) - Professional HTML/PDF reports (vs text logs) - Scheduled maintenance tasks (vs manual cron editing) --- ## ๐Ÿ”— Dependencies **Required Packages:** - `luci-base` - `rpcd` - `coreutils` - `coreutils-base64` **New Optional Packages (v0.3.5):** - `curl` - For diagnostics upload - `msmtp` - For SMTP email sending - `ca-certificates` - For HTTPS/TLS support - `wkhtmltopdf` - For PDF report generation (optional) - `rustdesk` - For remote management (optional) **Update Makefile:** ```makefile LUCI_DEPENDS:=+luci-base +rpcd +coreutils +coreutils-base64 \ +PACKAGE_luci-app-system-hub-email:msmtp \ +PACKAGE_luci-app-system-hub-email:ca-certificates \ +PACKAGE_luci-app-system-hub-remote:rustdesk ``` --- **Next Steps:** 1. Review this codex with team 2. Assign tasks to developers 3. Set up development branches 4. Begin Phase 1 (Diagnostics) implementation 5. Weekly progress reviews **Questions/Feedback:** Contact maintainers or open GitHub issue --- *Generated: 2025-12-28* *Codex Version: 1.0* *Target Release: 2025-01-20*