Files

4.4 KiB

name, version
name version
ops-portal-pipeline 2.0.0

Ops Portal — Architecture & Common Failure Modes

Created 2026-07-08 for ops.itpropartner.com. Updated 2026-07-12 with JS architecture fixes.

Data Pipeline

Data Collector (every 5 min) → /root/.hermes/scripts/ops-data-collector.py → writes /var/www/ops/data/ops-status.json → dashboard pages fetch /data/ops-status.json

JS Architecture

The portal uses TWO JavaScript files loaded on every page:

File Location What it exports
utils.js /opt/ops-portal/static/js/utils.js window.initNav, window.fetchStatus, window.escapeHtml, window.statusBadge, window.fmtTime
app.js /opt/ops-portal/static/js/app.js window.Ops (login, logout, isAuthenticated, getStatus, etc.), window.initNav, window.escapeHtml, window.fmtTime, window.fetchStatus

Both files MUST exist in the backend's static directory (/opt/ops-portal/static/js/). A second copy lives at /var/www/ops/js/ for Caddy's static file handler (controlled by /etc/caddy/Caddyfile). If either location goes out of sync, pages will 404 on one of the files.

Critical failure (Jul 12): utils.js existed at /var/www/ops/js/utils.js but NOT at /opt/ops-portal/static/js/utils.js — all pages referencing /js/utils.js got a 404. Fix: copy utils.js to the backend's static directory.

Auth Flow

Page loads → app.js checks localStorage.getItem('ops_token')
  → token exists? → hide login overlay, load page data
  → no token? → show login overlay, wait for credentials
  → user submits → POST /api/auth/login → store token in localStorage → load page

Token storage: localStorage (NOT sessionStorage). localStorage persists across tabs and browser restarts.

Credentials: germaine / itpp2026! (stored in /root/.hermes/.env as ADMIN_PASSWORD).

Nav Loading Pattern

Pages either have inline nav (index.html) or fetch nav dynamically:

Fetched nav pattern (most pages):

<div id="nav"></div>
...
fetch('/nav.html').then(function(r) { return r.text(); }).then(function(h) {
    document.getElementById('nav').innerHTML = h;
    if (typeof Ops.initNav === 'function') Ops.initNav();
}).catch(function(e) { console.warn('Nav failed:', e); });

The hamburger toggle has an inline onclick handler that toggles classList.toggle('open') on #navLinks. The Ops.initNav() function used to ALSO add an addEventListener that did the same toggle — causing both handlers to fire on every click, cancelling each other out. Fixed Jul 12: removed the duplicate toggle from initNav(). initNav now only handles:

  1. Active-link highlighting (.nav-link.active)
  2. Closing the menu when tapping outside (document click listener)

Common Failure Modes & Fixes

Symptom Root Cause Fix
Hamburger does nothing on mobile Duplicate toggle handler (inline onclick + initNav addEventListener) Remove addEventListener from initNav; inline onclick is sufficient
Hamburger does nothing (2) window.initNav is undefined Export window.initNav = initNav in app.js
Login overlay shows on every page load audit.html uses sessionStorage not localStorage Change to localStorage
Services/servers/backups crash on load getElementById('logoutBtn') called before nav fetch completes Wrap in interval or move inside fetch callback
cost.html blank on load window.fetchStatus is undefined Export window.fetchStatus = fetchStatus in app.js
config.html renders nothing window.escapeHtml is undefined Export window.escapeHtml = escapeHtml in app.js
JS/CSS files return 403 File permissions are 600 chmod 644 on all static files
JS returns wrong content-type Backend FileResponse without explicit media_type Set media_type explicitly or serve through Caddy file_server
Pages load stale broken JS Browser cached old version Add Cache-Control: no-cache headers and ?v=N on script tags
API shows 6/7 with one failing cloudflare_zones returns a list, not "ok" string Filter it out of api_checks in collector
Nav loaded but menu doesn't toggle nav.html fetched but inline onclick not firing Verify onclick attribute exists on toggle in nav.html

All Pages

/, /services.html, /servers.html, /backups.html, /network.html, /cron.html, /config.html, /logs.html, /audit.html, /cost.html, /fleettracker360.html, /nav.html