7.2 KiB
Ops Portal Full Code Audit — July 12, 2026
Auditor: Hermes | Pages: 11 | Total bugs: 42
The Four Root Causes
Everything else flows from these four:
RC-1: window.initNav is undefined (affects ALL pages)
app.js exports initNav only under window.Ops.initNav, not window.initNav.
Every page's guard typeof window.initNav === 'function' evaluates FALSE.
Nav hamburger, active-link, and logout wiring are dead on every page.
Fix (one line in app.js, inside IIFE before window.Ops = {...}):
window.initNav = initNav;
RC-2: utils.js does not exist
All pages reference /js/utils.js?v=2 but the file is /js/app.js.
The 404 is silent because app.js loads next and provides window.Ops.
But if the server returns a hard error, all pages break.
Fix: Rename app.js → utils.js OR update all <script src="/js/utils.js"> to app.js.
RC-3: logoutBtn DOM lookup before nav fetch completes
services.html, servers.html, backups.html all call
document.getElementById('logoutBtn').classList.add('show') synchronously.
logoutBtn lives in nav.html which is fetched asynchronously.
Result: TypeError on every authenticated page load on those 3 pages.
Fix: Move the getElementById('logoutBtn') call inside the fetch callback:
fetch('/nav.html').then(r => r.text()).then(h => {
document.getElementById('nav').innerHTML = h;
document.getElementById('logoutBtn').classList.add('show'); // ← here
if (typeof window.initNav === 'function') window.initNav();
});
RC-4: 6 of 11 pages have NO auth guard
network.html, cron.html, config.html, logs.html, cost.html, fleettracker360.html
load and show data without any Ops.isAuthenticated() check.
Full Bug Inventory by Page
index.html
- B1 [HIGH] utils.js 404 (silent)
- B2 [HIGH] window.initNav() call fails — window.initNav undefined
- B3 [MED] navUser shown via inline style, inconsistent with .show pattern
- B4 [MED] logoutBtn shown but never wired to logout (depends on initNav fix)
services.html
- S1 [CRIT] utils.js 404
- S2 [HIGH] login-overlay hardcoded class="show" — flash of login for auth'd users
- S3 [HIGH] loginError "Invalid credentials" visible without display:none
- S4 [CRIT] logoutBtn/navUser lookup before nav.html fetch completes → TypeError
- S5 [MED] window.initNav undefined (nav never initialized)
- S6 [MED] No guard for session expiry mid-session
servers.html
- V1 [CRIT] utils.js 404
- V2 [CRIT] logoutBtn.style.display = 'block' before nav loads → TypeError
- V3 [HIGH] Login form inputs have no CSS classes, no form-group wrapper — unstyled
- V4 [MED] loginError always shows hardcoded "Invalid credentials" text
- V5 [MED] window.initNav undefined
- V6 [LOW] No tags on login inputs (accessibility + autofill)
- V7 [LOW] login-logo uses emoji 🖥 instead of SVG (inconsistent)
backups.html
- K1 [CRIT] utils.js 404
- K2 [CRIT] logoutBtn.classList.add('show') before nav loads → TypeError
- K3 [HIGH] login-overlay hardcoded class="show"
- K4 [MED] loginError no display:none
- K5 [MED] window.initNav undefined
- K6 [HIGH] .summary-bar, .summary-item, .summary-label, .summary-val not in ops.css
network.html
- N1 [CRIT] utils.js 404
- N2 [HIGH] Scripts in <head> without defer (execute before DOM)
- N3 [CRIT] NO auth guard — page shows all network data without login
- N4 [MED] window.initNav undefined
- N5 [MED] Grafana link uses Tailscale IP 100.71.155.7 — unreachable without Tailscale
- N6 [LOW] Inline <style> redefines .card, .badge, .status-dot (may conflict with ops.css)
cron.html
- C1 [CRIT] utils.js 404
- C2 [HIGH] Scripts in <head> without defer
- C3 [CRIT] NO auth guard
- C4 [HIGH] placed AFTER the three
elements (inverted) - C5 [MED] window.initNav undefined
- C6 [LOW] app.js loaded but Ops.* never used — all utilities re-implemented locally
config.html
- G1 [CRIT] utils.js 404
- G2 [CRIT] window.escapeHtml() called throughout — not exported by app.js → TypeError
- G3 [HIGH] window.formatTime() used — not exported → falls back to Date.toLocaleString()
- G4 [HIGH] fetchStatus() called — not defined anywhere → typeof guard prevents crash but live data never loads
- G5 [CRIT] NO auth guard
- G6 [MED] window.initNav undefined
- G7 [HIGH] Local initNav() defined inside IIFE shadows concept, calls window.initNav (self-referencing risk)
- G8 [MED] .content-area and .page-footer not in ops.css
- G9 [MED] Uses but ops.css defines .page-header not .header
logs.html
- L1 [CRIT] utils.js 404
- L2 [HIGH] Scripts in <head> without defer
- L3 [CRIT] NO auth guard
- L4 [MED] window.initNav undefined
- L5 [MED] doesn't cleanly wrap content (navPlaceholder outside main, script inside )
audit.html
- A1 [CRIT] utils.js 404
- A2 [CRIT] Uses sessionStorage for token — all other pages use localStorage — token not found on nav
- A3 [MED] app.js loaded but Ops.* never used — own escapeHtml/fmtTime re-implemented
- A4 [MED] logoutBtn in nav never wired (initNav not called)
- A5 [MED] window.initNav undefined
- A6 [LOW] Login form pre-filled with value="germaine" — leaks valid username
cost.html
- T1 [CRIT] utils.js 404
- T2 [CRIT] window.fetchStatus(...) called — not defined anywhere → TypeError on load → no data renders
- T3 [CRIT] NO auth guard
- T4 [MED] app.js loaded but unused
- T5 [MED] window.initNav undefined
- T6 [LOW] Refresh button uses Unicode ↻ not SVG icon, .spinning animation doesn't apply
fleettracker360.html
- F1 [HIGH] No app.js or utils.js loaded — no auth system
- F2 [HIGH] NO auth guard
- F3 [MED] Missing viewport-fit=cover (all other pages have it)
- F4 [LOW] Hardcoded date "2026-07-12" in timestamp string
- F5 [LOW] COT hour calculation:
(utcHours + (-5) + 24).slice(-2)fails at midnight (produces "24") - F6 [LOW] Not linked from nav.html — orphaned page
Cross-Cutting Issues
| ID | Bug | Pages | Severity |
|---|---|---|---|
| X1 | /js/utils.js 404 | All 10 auth pages | CRIT |
| X2 | window.initNav undefined | All pages with fetch-nav | HIGH |
| X3 | logoutBtn null before nav loads | services, servers, backups | CRIT |
| X4 | No auth guard | network, cron, config, logs, cost, fleettracker | CRIT |
| X5 | login-overlay hardcoded show class | services, servers, backups | HIGH |
| X6 | Grafana link unreachable on mobile | nav.html + index.html | MED |
| X7 | ops.css vs ops.css?v=2 version inconsistency | Mixed across pages | LOW |
Priority Fix Order
- Add
window.initNav = initNav;to app.js (fixes X2, B2, S5, V5, K5, N4, C5, G6, L4, A5, T5) - Rename utils.js reference or file (fixes X1)
- Move logoutBtn lookups inside nav fetch callback (fixes X3)
- Replace
window.fetchStatus(...)in cost.html with direct fetch (fixes T2) - Add
window.escapeHtml = Ops.escapeHtmlto app.js or fix config.html (fixes G2) - Change audit.html to use localStorage not sessionStorage (fixes A2)
- Add auth guard + login overlay to network, cron, config, logs, cost (fixes X4)
- Remove hardcoded
showclass from login-overlay in services/servers/backups HTML (fixes X5) - Fix placement in cron.html (fixes C4)
- Add .summary-bar CSS to ops.css (fixes K6)