Add structured headers to the PHP include layer, fix monitor state paths

All 16 include/ files now carry PURPOSE / DESIGN PRINCIPLES / OPERATIONAL
SAFEGUARDS / EXPORTS / CONFIGURATION, keeping the first three section names
identical to the bash headers so retrieval can route across both languages.

monitor.php read six watchdog state files from /tmp while the watchdogs write
to STATE_DIR, so every strike set came back empty and the summary reported
healthy unconditionally. docs.php gained path containment before it is wired
to a page.
This commit is contained in:
Gmer4Lfe
2026-08-02 00:38:22 -04:00
parent 76c4ca5ccf
commit 43b5443b30
16 changed files with 811 additions and 21 deletions
+62 -10
View File
@@ -1,7 +1,59 @@
<?php
require_once __DIR__ . '/common.php';
// Monitor-page-specific helpers — partner state, fallback state, watchdog summary, scripts status.
// ═══════════════════════════════════════════════════════════════════════════════════════════════
// PURPOSE
// Monitor-page roll-ups that are not raw system metrics: partner reachability, fallback
// state, the single-glance watchdog health summary, script run status, and rsync progress.
// Raw hardware numbers come from common.php; this file answers "is anything wrong".
//
// DESIGN PRINCIPLES
// One boolean has to be trustworthy.
// vv_watchdog_summary() reduces every watchdog's state to 'healthy'. It is the only
// thing most people look at, so it is conjunctive — healthy requires every strike set
// empty, every level zero, the NIC up and sshd alive. Any doubt resolves to not-healthy.
//
// State paths derive from STATE_DIR, never hardcoded.
// The watchdogs write under STATE_DIR, which follows SCRIPTS_DIR through a storage-mode
// migration. Hardcoding an absolute path here silently decouples the page from the
// scripts — see OPERATIONAL SAFEGUARDS.
//
// Summarises; does not re-derive.
// Strike counts come from the files the watchdogs wrote. This file never recomputes
// whether a container is unhealthy — that decision belongs to the watchdog that owns it.
//
// OPERATIONAL SAFEGUARDS
// Missing state must not read as healthy — and once did.
// Six state files were read from /tmp while the watchdogs write to STATE_DIR. Every
// read returned empty, every strike set came back clear, and 'healthy' was therefore
// always true: a permanent false all-clear on the page whose whole job is raising the
// alarm. Fixed 2026-08-02. If a strike set ever looks suspiciously empty, verify the
// path against where the watchdog actually writes before trusting it.
//
// Live stability probes are cheap and time-boxed.
// df, sensors, pgrep and ps run per render, so each is a single command with stderr
// discarded and a scalar result. Nothing here iterates over containers or disks.
//
// Shell arguments are escaped.
// Paths passed to df go through escapeshellarg(); the NIC name is read from sysfs
// rather than interpolated from user input.
//
// Read-only. Reports on watchdogs, fallback and scripts; never starts, stops, or clears any
// of them.
//
// EXPORTS
// vv_partner_state() partner reachability and identity
// vv_fallback_state() current fallback state for this host
// vv_fallback_active() whether this host is currently covering, and what
// vv_watchdog_summary() the health roll-up described above
// vv_scripts_status() last-run status per scheduled script
// vv_rsync_status() current/last rsync progress
//
// CONFIGURATION
// STATE_DIR fallback_state.db, container/resource/system/storage/network watchdog state,
// system_watchdog_oom.db, system_watchdog_reboots.db
// DATA_DIR container_restart_history.db
// ═══════════════════════════════════════════════════════════════════════════════════════════════
function vv_partner_state(): array {
$vars = vv_conf_vars();
@@ -138,8 +190,8 @@ function vv_watchdog_summary(): array {
return $out;
};
$dock = $parseKv(@file_get_contents('/tmp/container_watchdog_state.db') ?: '');
$rw = $parseKv(@file_get_contents('/tmp/resource_watchdog_state.db') ?: '');
$dock = $parseKv(@file_get_contents(STATE_DIR . '/container_watchdog_state.db') ?: '');
$rw = $parseKv(@file_get_contents(STATE_DIR . '/resource_watchdog_state.db') ?: '');
$ctrStrikes = [];
foreach ($dock as $k => $v) {
@@ -169,10 +221,10 @@ function vv_watchdog_summary(): array {
$rwLevel = (int)($rw['rm_action_level'] ?? 0);
$daemonStrikes = (int)($dock['daemon_strikes'] ?? 0);
$oomCount = (int)trim(@file_get_contents('/tmp/system_watchdog_oom.db') ?: '0');
$oomCount = (int)trim(@file_get_contents(STATE_DIR . '/system_watchdog_oom.db') ?: '0');
// ── Stability watchdog strikes (/tmp/system_watchdog_state.db) ───────────
$stabRaw = @file_get_contents('/tmp/system_watchdog_state.db') ?: '';
// ── Stability watchdog strikes (STATE_DIR) ───────────
$stabRaw = @file_get_contents(STATE_DIR . '/system_watchdog_state.db') ?: '';
$stabStrikes = [];
foreach (explode("\n", $stabRaw) as $line) {
$line = trim($line);
@@ -182,8 +234,8 @@ function vv_watchdog_summary(): array {
if ($count > 0) $stabStrikes[trim($k)] = $count;
}
// ── Storage watchdog strikes (/tmp/storage_watchdog_state.db) ────────────
$storRaw = @file_get_contents('/tmp/storage_watchdog_state.db') ?: '';
// ── Storage watchdog strikes (STATE_DIR) ────────────
$storRaw = @file_get_contents(STATE_DIR . '/storage_watchdog_state.db') ?: '';
$growthStrikes = []; $logStrikes = [];
foreach (explode("\n", $storRaw) as $line) {
$line = trim($line);
@@ -198,8 +250,8 @@ function vv_watchdog_summary(): array {
$logStrikes[substr($key, strlen('appdata_log_'))] = $count;
}
// ── Network watchdog NPM strikes (/tmp/network_watchdog_state.db) ────────
$netRaw = @file_get_contents('/tmp/network_watchdog_state.db') ?: '';
// ── Network watchdog NPM strikes (STATE_DIR) ────────
$netRaw = @file_get_contents(STATE_DIR . '/network_watchdog_state.db') ?: '';
$npmStrikes = 0;
foreach (explode("\n", $netRaw) as $line) {
$line = trim($line);