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
+60 -4
View File
@@ -1,6 +1,55 @@
<?php
// Docs — markdown file discovery, $VAR substitution, and rendering.
// Requires parsedown or similar. Falls back to <pre> if not available.
// ═══════════════════════════════════════════════════════════════════════════════════════════════
// PURPOSE
// Renders the repo's own markdown — READMEs, Manuals, design notes — inside the WebGUI,
// substituting live conf values into `$VAR` markers so documentation shows what this host
// is actually configured to do rather than a generic example.
//
// STATUS
// Not currently wired. Nothing requires this file and there is no docs page or endpoint
// yet. It is kept because the per-folder README/Manual corpus is exactly what it exists to
// surface. Written to be safe on the day it is connected — see OPERATIONAL SAFEGUARDS.
//
// DESIGN PRINCIPLES
// Documentation is discovered, not enumerated.
// vv_docs_tree() walks SCRIPTS_DIR for *.md. A new folder README appears in the UI
// with no registration step, which is what keeps the docs from drifting out of the
// navigation.
//
// Live values, not example values.
// `$VAR_NAME` in a markdown file is replaced with that variable's current value from
// conf. Unresolved names render in a distinct class rather than being left as-is, so a
// stale variable reference in a doc is visible instead of looking like prose.
//
// Degrades to readable text without Parsedown.
// If the bundled renderer is absent the raw markdown is emitted in a <pre> block.
// Missing a formatter reduces presentation; it never hides the content.
//
// OPERATIONAL SAFEGUARDS
// Paths are contained to SCRIPTS_DIR.
// $rel is resolved with realpath() and required to remain under SCRIPTS_DIR, be a
// regular file, and carry a .md extension. This is deliberate defence for a parameter
// that will arrive from a request the moment this is wired up — without it, a
// traversal sequence reaches any file the web user can read.
//
// Markdown is rendered in safe mode.
// Parsedown runs with setSafeMode(true), and the <pre> fallback escapes everything.
// These files are trusted today, but they are also synced between hosts.
//
// Substituted conf values are escaped.
// htmlspecialchars() is applied to both the value and the variable name, so a conf
// value containing markup cannot inject into the rendered page.
//
// Read-only. Discovers and renders; never writes a doc.
//
// EXPORTS
// vv_docs_tree() every *.md under SCRIPTS_DIR, relative paths, sorted
// vv_docs_render() one file to HTML with conf substitution applied
//
// CONFIGURATION
// SCRIPTS_DIR the containment root and the discovery root
// PARSEDOWN_PATH /usr/local/emhttp/plugins/varaverk/lib/Parsedown.php — optional
// ═══════════════════════════════════════════════════════════════════════════════════════════════
require_once __DIR__ . '/config.php';
@@ -24,8 +73,15 @@ function vv_docs_tree(): array {
}
function vv_docs_render(string $rel, array $vars): string {
$path = SCRIPTS_DIR . '/' . $rel;
if (!file_exists($path)) return '<p>File not found.</p>';
// Containment check — $rel is expected to come from a request parameter once this is
// wired to a page. Resolve it and require the result to stay inside SCRIPTS_DIR and to
// still be a .md file, so a traversal sequence cannot reach arbitrary files.
$base = realpath(SCRIPTS_DIR);
$path = realpath(SCRIPTS_DIR . '/' . $rel);
if ($base === false || $path === false) return '<p>File not found.</p>';
if (!str_starts_with($path, $base . '/')) return '<p>File not found.</p>';
if (strtolower(pathinfo($path, PATHINFO_EXTENSION)) !== 'md') return '<p>File not found.</p>';
if (!is_file($path)) return '<p>File not found.</p>';
$md = file_get_contents($path);