# Ops Portal Jul 12 Cleanup Audit

42 bugs found across 11 pages by Claude Sonnet 4-6 subagent.

## Root Causes (5 issues causing 80% of bugs)

### 1. `/js/utils.js` 404
`utils.js` existed at `/var/www/ops/js/utils.js` but NOT at `/opt/ops-portal/static/js/` (the backend's JS directory). Every page referenced `/js/utils.js` which returned 404 via Caddy's `/js/*` file_server handler. Fix: `cp /var/www/ops/js/utils.js /opt/ops-portal/static/js/utils.js`

### 2. `window.initNav` undefined
`initNav()` is exported as `window.Ops.initNav` (via `app.js`), not `window.initNav`. Every page calling `window.initNav()` calls undefined. Fix: Pages must call `Ops.initNav()`, or export `window.initNav = initNav` in app.js.

### 3. `logoutBtn` DOM lookup before nav fetch
Pages services.html, servers.html, backups.html call `document.getElementById('logoutBtn')` synchronously before the `fetch('/nav.html')` callback completes. The nav (and `logoutBtn`) doesn't exist yet → TypeError. Fix: Move all `getElementById('logoutBtn')` calls inside the fetch callback.

### 4. Pages missing required script files
Some pages loaded only `app.js` (missing `utils.js`), others loaded only `utils.js` (missing `app.js`). Fix: EVERY page must load BOTH:
```html
<script src="/js/utils.js?v=2"></script>
<script src="/js/app.js?v=2"></script>
```

### 5. No auth guard on 6 pages
network.html, cron.html, config.html, logs.html, cost.html, fleettracker360.html have no login overlay or auth check. Fix: Add login overlay + `Ops.isAuthenticated()` guard.

## Critical Bugs by Page

| Page | Critical Bugs | File Path |
|------|------|-----------|
| index.html | 1 | /opt/ops-portal/static/index.html |
| services.html | 3 | /opt/ops-portal/static/services.html |
| servers.html | 2 | /opt/ops-portal/static/servers.html |
| backups.html | 2 | /opt/ops-portal/static/backups.html |
| network.html | 2 | /opt/ops-portal/static/network.html |
| cron.html | 2 | /opt/ops-portal/static/cron.html |
| config.html | 4 | /opt/ops-portal/static/config.html |
| logs.html | 2 | /opt/ops-portal/static/logs.html |
| audit.html | 2 | /opt/ops-portal/static/audit.html |
| cost.html | 3 | /opt/ops-portal/static/cost.html |
| fleettracker360.html | 0 | /opt/ops-portal/static/fleettracker360.html |

## Quick Fixes Applied Jul 12
- Copied utils.js to backend static dir → 404 fixed
- Added cache busting `?v=2` to all JS/CSS
- Fixed Grafana link from 127.0.0.1 to Tailscale IP
- Added z-index: 1000 to nav-links
- Added inline onclick fallback to nav-toggle
- Hid "Invalid credentials" error text by default
- Both JS files added to all 10 pages

## Remaining Work
- Export `window.initNav` properly
- Fix `logoutBtn` timing on services/servers/backups
- Add auth guards to 6 unprotected pages
- Fix `window.fetchStatus` on cost.html
- Fix `window.escapeHtml` on config.html
- Fix audit.html `sessionStorage` → `localStorage`
