Add structured headers to the PHP pages layer
Documents each tab's purpose, what it renders, and which endpoints it polls. Pages that start with markup get the header in a <?php ?> block so it never reaches the browser. Also corrects the layer diagram in README-unraid.md: eight of eleven pages hold no PHP logic and poll api/ for everything — only auth, monitor and scheduler require an include/ file directly.
This commit is contained in:
@@ -85,14 +85,19 @@ templates, and the WebGUI install path.
|
||||
## ━━━ THE WEB UI — THREE LAYERS ━━━
|
||||
|
||||
```
|
||||
pages/*.php what you look at ── requires ──► include/
|
||||
pages/*.php what you look at ── polls ─────► api/
|
||||
api/*.php what the page fetches ── requires ──► include/
|
||||
include/*.php the actual logic — vv_*() functions, shared by both
|
||||
include/*.php the actual logic — vv_*() functions
|
||||
```
|
||||
|
||||
The split matters: a page and its API endpoint call **the same** `vv_*()` builders, so a
|
||||
cached response and a live one cannot disagree in shape. Adding a metric means adding it in
|
||||
`include/` once, and both the page and the endpoint get it.
|
||||
**Most pages hold no logic at all.** Eight of the eleven are pure view — markup, CSS and a
|
||||
poll loop, with every value arriving as JSON from `api/`. Only `auth.php`, `monitor.php` and
|
||||
`scheduler.php` require an `include/` file directly, and then only to server-render their
|
||||
initial state; their mutations still go through endpoints.
|
||||
|
||||
That is why the layer split holds: a page and its endpoint cannot disagree about what a value
|
||||
means, because the page does not compute it. Adding a metric means adding it in `include/`
|
||||
once, and the endpoint, the cache writer, and the page all pick it up together.
|
||||
|
||||
| Layer | Files | Role |
|
||||
|-------|-------|------|
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Arrs tab. Library counts, queue state, root folders and recent cleanup/discovery activity
|
||||
// for every Sonarr / Radarr / Lidarr instance across all nodes.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Pure view — markup plus a poll against api/arrs.php. Instance discovery, live fetching
|
||||
// and stats parsing all live in include/arrs.php.
|
||||
//
|
||||
// Local nodes are live, remote nodes are cached. The page surfaces cache age rather than
|
||||
// hiding it, so a 2-hour-old partner count is never presented as current.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Read-only with respect to media. Nothing here triggers a scan, import, or deletion —
|
||||
// the arr cleanups are scheduled scripts, not page buttons.
|
||||
//
|
||||
// A node with no cache yet renders as "not collected", distinct from a node that genuinely
|
||||
// has an empty library.
|
||||
//
|
||||
// RENDERS
|
||||
// Per-node arr cards: tracked counts, queue, root folders, cleanup and discovery stats
|
||||
// Inline conf editing for arr-related settings
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/arrs.php polled every 60s → include/arrs.php
|
||||
// api/confform.php inline conf edits → include/confform.php
|
||||
?>
|
||||
<style>
|
||||
/* ── Cards ───────────────────────────────────────────────── */
|
||||
.vv-arr-card { background:#161616;border:1px solid #2a2a2a;border-radius:6px;padding:12px 14px;min-width:0; }
|
||||
|
||||
@@ -1,3 +1,47 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Auth tab. Manages the stack sitting in front of every protected hostname — NPM proxy
|
||||
// hosts and certificates, LLDAP users and groups, and Authelia access-control rules.
|
||||
//
|
||||
// OPERATIONAL MODEL
|
||||
// The most consequential page in the UI. A wrong edit here does not render badly, it locks
|
||||
// people out of every service or exposes one that should be protected.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Requires include/auth.php directly rather than going through an endpoint for everything.
|
||||
// Server-rendered for the initial state, with api/auth.php handling mutations. The
|
||||
// credentials involved never reach the browser either way.
|
||||
//
|
||||
// Only the owner host edits auth config.
|
||||
// Changes are made here and reach the partner through Critical-Data sync, not by the
|
||||
// browser writing to two hosts. One source of truth, one direction of travel.
|
||||
//
|
||||
// Authelia rules are edited as a block, preserving the rest of the YAML untouched.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Every destructive action is confirmed — deleting a user, removing a proxy host, or
|
||||
// rewriting the rule set are all one click away from locking out a household.
|
||||
//
|
||||
// Rule writes are atomic and refuse a missing config. include/auth.php writes to a temp
|
||||
// file and renames; a missing configuration.yml is an error, never a freshly created file
|
||||
// with a permissive default policy.
|
||||
//
|
||||
// Certificate state is read-only here. Renewal is owned by the cert monitor.
|
||||
//
|
||||
// All values render escaped — usernames, domains and rule fields are attacker-adjacent
|
||||
// strings by definition on this page.
|
||||
//
|
||||
// RENDERS
|
||||
// NPM proxy host list and editor, certificate status
|
||||
// LLDAP user and group management
|
||||
// Authelia access-control rules and default policy
|
||||
//
|
||||
// DEPENDS ON
|
||||
// include/auth.php required directly for initial render
|
||||
// api/auth.php mutations
|
||||
// api/cert.php certificate status
|
||||
?>
|
||||
<style>
|
||||
/* ── Toolbar ─────────────────────────────────────────────────────────────── */
|
||||
.vv-au-toolbar { display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap; }
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Docker tab. Container inventory grouped into Varaverk-owned folders, with start / stop /
|
||||
// restart controls and WebUI links.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Pure view — inventory and folder state come from api/docker.php; actions go to
|
||||
// api/docker_action.php. Folder storage and the conf mirror live in include/docker.php.
|
||||
//
|
||||
// Folders are Varaverk's own, not folder.view3's. The grouping survives that plugin being
|
||||
// absent or reset; it is synced to only when installed.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Destructive actions are confirmed in the browser before the request is sent.
|
||||
//
|
||||
// Container actions are routed through a dedicated action endpoint that validates the name
|
||||
// against the real inventory — the page never composes a docker command.
|
||||
//
|
||||
// Container names are escaped on render, so a name containing markup cannot inject.
|
||||
//
|
||||
// RENDERS
|
||||
// Folder-grouped container grid, per-container state, WebUI links, action buttons
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/docker.php polled every 60s → include/docker.php
|
||||
// api/docker_action.php start/stop/restart
|
||||
?>
|
||||
<style>
|
||||
.vv-dk-toolbar { display:flex;align-items:center;gap:8px;margin-bottom:12px;padding:0 2px;flex-wrap:wrap; }
|
||||
.vv-dk-title { font-size:13px;font-weight:bold;color:#888;text-transform:uppercase;letter-spacing:.06em;flex:1; }
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Fallback tab. Current state of every node (NORMAL / FALLBACK / NO_INTERNET / DARK),
|
||||
// which tiers have activated, handback strike progress, and which covered containers are
|
||||
// actually running.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Pure view — markup plus a poll against api/fallback.php. State parsing lives in
|
||||
// include/fallback.php.
|
||||
//
|
||||
// Reports what each node believes about itself. Remote state is read from the partner's own
|
||||
// state file rather than inferred from what this host can reach.
|
||||
//
|
||||
// Polls faster than most tabs (30s) because this is the page someone opens during an
|
||||
// outage, when stale numbers are actively misleading.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Read-only. The page cannot trigger a failover, force a handback, or start a covered
|
||||
// container. Fallback is driven by fallback.sh reacting to real reachability, and a manual
|
||||
// override from a browser is exactly the wrong way to enter that state.
|
||||
//
|
||||
// A missing state file renders as unknown, never as NORMAL — claiming healthy for a
|
||||
// fallback process that is not running would be the worst possible error on this page.
|
||||
//
|
||||
// RENDERS
|
||||
// Per-node state, tier activation and delays, handback strikes, covered container status
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/fallback.php polled every 30s → include/fallback.php
|
||||
// api/confform.php inline conf edits → include/confform.php
|
||||
?>
|
||||
<style>
|
||||
/* ── Existing status styles ── */
|
||||
.vv-fb-active { background:#1a1200;border:1px solid #5a3800;border-radius:6px;padding:12px 14px; }
|
||||
|
||||
@@ -1,4 +1,50 @@
|
||||
<?php require_once dirname(__DIR__) . '/include/monitor.php'; ?>
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Monitor tab. The main dashboard — CPU per core, memory, GPUs, disks and pools, network,
|
||||
// UPS, VMs, containers, transcodes, media sessions, and the watchdog health roll-up, for
|
||||
// this host and every partner.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Two poll rates, deliberately split.
|
||||
// api/monitor_fast.php carries the cheap, fast-moving values (1–2s); api/monitor.php
|
||||
// carries the full payload on a slower cycle. Everything refreshing at the fast rate
|
||||
// would put real load on the WebGUI this page exists to watch.
|
||||
//
|
||||
// Served from the tmpfs cache, not live calls.
|
||||
// api_cache_writer.sh refreshes the payload every minute and the endpoint serves that.
|
||||
// ?live=1 bypasses it. A missing cache always falls back to a live call, so the cache
|
||||
// can never be why the dashboard fails to load.
|
||||
//
|
||||
// Missing subsystems simply do not render.
|
||||
// No GPU, no UPS, no VMs — the corresponding card is absent rather than showing zeros
|
||||
// or an error. The page is built to be correct on hardware lacking any given part.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// The health roll-up must not default to healthy.
|
||||
// vv_watchdog_summary() is conjunctive across every strike set, and it reads state from
|
||||
// STATE_DIR. Six of those paths once pointed at /tmp, every read returned empty, and
|
||||
// the page reported healthy unconditionally (fixed 2026-08-02). If this panel looks
|
||||
// suspiciously green, verify the paths before believing it.
|
||||
//
|
||||
// Container actions are confirmed and routed through the action endpoint, which validates
|
||||
// against real inventory.
|
||||
//
|
||||
// All remote and container-supplied strings render escaped.
|
||||
//
|
||||
// RENDERS
|
||||
// System header, CPU per core, memory breakdown, GPU cards, storage pools and array disks,
|
||||
// network, UPS, VMs, containers, transcode sessions, media now-playing, watchdog summary,
|
||||
// partner node cards
|
||||
//
|
||||
// DEPENDS ON
|
||||
// include/monitor.php required directly for initial render
|
||||
// api/monitor.php full payload, slower cycle
|
||||
// api/monitor_fast.php fast-moving values, 1–2s
|
||||
// api/system.php system info
|
||||
// api/media.php now-playing sessions
|
||||
// api/docker_action.php container actions
|
||||
// api/flag_toggle.php toggles
|
||||
<style>
|
||||
@keyframes vvRsPulse {
|
||||
0%,100% { opacity:.5; transform:scaleX(.9); }
|
||||
|
||||
@@ -1,3 +1,41 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Partnership tab. The mesh view — which nodes exist, whether they are reachable over
|
||||
// Tailscale, their system summary, sync history, and the onboarding controls that deploy
|
||||
// stacks to a partner.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Pure view — all node data comes from api/partnership.php; actions are separate endpoints.
|
||||
// Reachability, SSH and system collection live in include/partnership.php.
|
||||
//
|
||||
// Reachability is probed on demand as well as polled, because "is my partner up right now"
|
||||
// is the question this page exists to answer.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Every action that changes a partner is confirmed first — this page can deploy stacks and
|
||||
// provision credentials on a machine 50 miles away, and there is no undo for that.
|
||||
//
|
||||
// Long-running operations go through api/run.php rather than blocking the page, so a deploy
|
||||
// that takes minutes does not leave the browser hanging on a request.
|
||||
//
|
||||
// An unreachable partner degrades to its own card only; the rest of the mesh still renders.
|
||||
//
|
||||
// Values from remote nodes are escaped on render — this page displays strings originating
|
||||
// on another machine.
|
||||
//
|
||||
// RENDERS
|
||||
// Node cards with identity, reachability, system summary, sync history
|
||||
// Onboarding and stack-deploy controls, API key provisioning, partnership settings
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/partnership.php polled every 10s → include/partnership.php
|
||||
// api/partnership_ping.php on-demand reachability probe
|
||||
// api/partnership_settings.php settings writes
|
||||
// api/create_api_key.php credential provisioning
|
||||
// api/run.php long-running deploy operations
|
||||
// api/confform.php inline conf edits
|
||||
?>
|
||||
<style>
|
||||
.vv-pt-grid { display:grid; gap:12px; }
|
||||
.vv-pt-node { background:#161616; border:1px solid #2a2a2a; border-radius:6px; padding:12px; min-width:0; }
|
||||
|
||||
@@ -1,3 +1,42 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Rsync tab. Sync profiles, share lists, transfer progress, per-run history, and manual
|
||||
// sync triggers.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Pure view — profile and status data from api/rsync.php, profile edits through
|
||||
// api/rsync_profiles.php, manual runs through api/manual_sync.php.
|
||||
//
|
||||
// Progress polls fast (2s) while a transfer is live and falls back to the slow interval
|
||||
// otherwise, so an idle page is not hammering the endpoint.
|
||||
//
|
||||
// Profiles are edited as structured data, not as raw rsync flags typed by hand.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Manual sync is confirmed before it fires. A sync moves real data between two machines and
|
||||
// is not something to trigger with a stray click.
|
||||
//
|
||||
// The page shows the global RSYNC_ENABLED gate alongside the per-tier toggles, so a run
|
||||
// that will be skipped by the gate is visibly skipped rather than silently doing nothing.
|
||||
//
|
||||
// Heavy escaping throughout — share paths, profile names and rsync output all render as
|
||||
// text, never as markup.
|
||||
//
|
||||
// The page does not compose rsync flags. Deletion semantics in particular are owned by
|
||||
// Rsync/rsync.sh, where the pass-1-must-complete interlock lives.
|
||||
//
|
||||
// RENDERS
|
||||
// Profile editor, share lists, live transfer progress, run history, manual sync controls
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/rsync.php status, polled 2s live / 30s idle
|
||||
// api/rsync_profiles.php profile read and write
|
||||
// api/manual_sync.php manual run trigger
|
||||
// api/rsync_win_arrays.php share array editing
|
||||
// api/flag_toggle.php enable/disable toggles
|
||||
// api/confform.php inline conf edits
|
||||
?>
|
||||
<style>
|
||||
.vv-ry-card { background:#161616;border:1px solid #2a2a2a;border-radius:6px;padding:10px 12px;min-width:0; }
|
||||
.vv-ry-sec { font-size:10px;font-weight:bold;color:#444;letter-spacing:.07em;text-transform:uppercase;margin-bottom:6px; }
|
||||
|
||||
@@ -1,4 +1,63 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Scheduler tab. The largest page in the plugin and the main operational surface: the full
|
||||
// script library, per-job schedules, live run status and logs, dry-run output, conf editing
|
||||
// per script, and the custom-script editor.
|
||||
//
|
||||
// OPERATIONAL MODEL
|
||||
// Writes state that changes what the machine does on a timer. Enabling, disabling or
|
||||
// rescheduling a job here takes effect on the next cron rebuild — this page decides what
|
||||
// runs unattended at 1am.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Script descriptions come from the scripts themselves.
|
||||
// Requires include/scheduler.php, which parses the PURPOSE block out of each bash
|
||||
// header. The library listing and the script's own documentation are the same text and
|
||||
// cannot drift. This page is the reason the repo-wide header convention exists.
|
||||
//
|
||||
// The job tree is derived from conf, not maintained here.
|
||||
// Orchestrator job lists come from master.conf arrays; custom scripts are whatever
|
||||
// *.sh sits in CUSTOM_SCRIPTS_DIR. Nothing has to be registered in two places.
|
||||
//
|
||||
// Long operations never block the page.
|
||||
// Runs, dry-runs and imports go through api/run.php and api/dryrun.php with status
|
||||
// polled separately, so a script that takes ten minutes does not hold a request open.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Running a script from the UI is confirmed first. Several of these delete files.
|
||||
//
|
||||
// Dry-run is offered alongside run for anything destructive, and its output is shown in
|
||||
// full rather than summarised — reading the list is the point.
|
||||
//
|
||||
// Stale locks are cleared explicitly through api/clearlock.php, never automatically. A lock
|
||||
// that looks stale may belong to a job still running.
|
||||
//
|
||||
// Conf edits are surgical, preserving the comment blocks that document every threshold.
|
||||
//
|
||||
// Custom scripts live outside the git repo, so a user's own scripts are never touched by a
|
||||
// pull and never committed by accident.
|
||||
//
|
||||
// Script content and log output render escaped throughout — this page displays arbitrary
|
||||
// file contents.
|
||||
//
|
||||
// RENDERS
|
||||
// Job tree by orchestrator tier, per-job schedule and toggle controls, live status and
|
||||
// logs, dry-run output, per-script conf forms, custom script editor, run history
|
||||
//
|
||||
// DEPENDS ON
|
||||
// include/scheduler.php required directly — schedule, cron rebuild, script library
|
||||
// api/scheduler.php schedule read/write api/run.php execute
|
||||
// api/dryrun.php dry-run execute api/stop.php terminate
|
||||
// api/status.php live run status api/log.php log tail
|
||||
// api/script.php script read/write api/readscript.php source
|
||||
// api/scriptinfo.php header metadata api/import_script.php
|
||||
// api/conf_toggle.php per-script enable api/flag_toggle.php
|
||||
// api/confform.php conf forms api/rawconf.php raw conf edit
|
||||
// api/board.php overview board api/recent.php recent runs
|
||||
// api/snapshot.php state snapshot api/clearlock.php stale lock clear
|
||||
// api/savefolders.php folder grouping api/reorderarray.php
|
||||
// api/rsync_standalone.php
|
||||
require_once dirname(__DIR__) . '/include/scheduler.php';
|
||||
|
||||
// Setup mode — auto-open a conf file and force the editing sequence
|
||||
|
||||
@@ -1,4 +1,33 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Settings tab. Varaverk's own configuration — storage mode, global toggles, and the conf
|
||||
// fields that are not specific to any one subsystem.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Edits go through the same conf machinery the scheduler page uses (include/confform.php),
|
||||
// so a value changed here is written exactly the way a value changed anywhere else is —
|
||||
// surgically, preserving comments and ordering.
|
||||
//
|
||||
// Storage mode is presented as a migration, not a setting. Changing it moves the whole
|
||||
// installation and regenerates the cron, which is why it routes through api/storage.php
|
||||
// rather than a plain conf write.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// The storage-mode change is confirmed before it runs. It is the most destructive operation
|
||||
// reachable from the UI — rsync --delete, rm -rf, and a rewrite of every derived path.
|
||||
//
|
||||
// Conf writes are surgical. A settings page that regenerated master.conf would destroy the
|
||||
// comment blocks that document every threshold in it.
|
||||
//
|
||||
// Values are escaped on render and on write-back.
|
||||
//
|
||||
// RENDERS
|
||||
// Storage mode selector, global toggles, general conf fields
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/confform.php conf read/write → include/confform.php
|
||||
// api/storage.php storage-mode migration
|
||||
$_myHost = vv_detect_host();
|
||||
$_vars = vv_conf_vars();
|
||||
$_myId = strtoupper($_myHost);
|
||||
|
||||
@@ -1,4 +1,37 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Setup tab. First-run wizard — walks a fresh install through host identity, credentials,
|
||||
// API key creation, storage mode, and the readiness checklist.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// The checklist is derived, never stored. api/checklist.php re-evaluates real state on each
|
||||
// load, so a step cannot be marked complete while the thing it checks is actually missing.
|
||||
//
|
||||
// Setup state is pushed to partners. Once a node knows who it is, that identity is shared
|
||||
// through vv_push_setup_state() rather than typed twice.
|
||||
//
|
||||
// Detection over interrogation. Where a value can be read from a running service, setup
|
||||
// reads it instead of asking — the same principle conf_populate.sh follows.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Existing values are not overwritten by detection. A field already filled in stays as it
|
||||
// is; the wizard fills gaps rather than resetting a working install.
|
||||
//
|
||||
// Ambiguous detection is refused rather than guessed — a container prefix matching two
|
||||
// containers is reported for manual resolution, never picked arbitrarily.
|
||||
//
|
||||
// Credentials entered here are written to host*.conf, which is gitignored. They are never
|
||||
// committed and never leave the node except through the explicit partner push.
|
||||
//
|
||||
// RENDERS
|
||||
// Step-by-step wizard, readiness checklist, credential entry, API key creation
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/setup.php wizard state and writes
|
||||
// api/checklist.php live readiness evaluation
|
||||
// api/create_api_key.php unraid-api key provisioning
|
||||
// api/storage.php storage-mode selection
|
||||
// First-run setup wizard — uniform flow for all hosts.
|
||||
// Step 1: auto-detect environment + server identity form.
|
||||
// Step 2: auto-populate + guide + checklist.
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
<?php
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
// PURPOSE
|
||||
// Watchdog tab. Shows what every watchdog has recorded across all nodes — strike counts,
|
||||
// action levels, paused and stopped containers, restart history, OOM and reboot counts.
|
||||
//
|
||||
// DESIGN PRINCIPLES
|
||||
// Pure view. No PHP logic and no include/ dependency — the whole page is markup plus a
|
||||
// poll against api/watchdog.php. All parsing lives in include/watchdog.php behind that
|
||||
// endpoint, so the page cannot hold a second opinion about what a strike means.
|
||||
//
|
||||
// Shows every node, not just this one. A watchdog page that only covered the host you
|
||||
// happened to open it on would miss exactly the node in trouble.
|
||||
//
|
||||
// OPERATIONAL SAFEGUARDS
|
||||
// Strictly read-only. There is no control on this page that clears a strike, restarts a
|
||||
// container, or resets a counter — those belong to the watchdog that owns the state.
|
||||
//
|
||||
// A node that fails to report renders as unavailable rather than healthy. Absence of data
|
||||
// is never drawn as an all-clear.
|
||||
//
|
||||
// RENDERS
|
||||
// Per-node cards: resource / docker / system / storage / network watchdog state,
|
||||
// strike pills, restart history, reboot and OOM counts
|
||||
//
|
||||
// DEPENDS ON
|
||||
// api/watchdog.php polled every 30s → include/watchdog.php
|
||||
?>
|
||||
<style>
|
||||
.vv-wd-card { background:#161616;border:1px solid #2a2a2a;border-radius:6px;padding:10px;min-width:0; }
|
||||
.vv-wd-sec { font-size:10px;font-weight:bold;color:#444;letter-spacing:.07em;text-transform:uppercase;margin-bottom:6px; }
|
||||
|
||||
Reference in New Issue
Block a user