# Session Closeout: Live Dashboard at pezant.ca/dashboard (2026-04-17)
## Summary
Built and deployed a live infrastructure dashboard at `pezant.ca/dashboard`, wiring up the existing frontend skeleton to real data sources and fixing the OAuth return-to-origin flow.
## What Was Done
### 1. Apache Proxy Configuration
– Added `RewriteRule` for `/dashboard` → port 3003 in Apache config on VM
– Added OIDC exemption for `POST /tools/dashboard/api/metrics` (placed **after** the `/tools` OIDC block so it overrides correctly)
– Reloaded Apache — dashboard accessible at `pezant.ca/dashboard`
### 2. Metrics Push Script (`scripts/push-metrics.sh`)
– Created push script that runs locally in WSL every 5 minutes
– Collects **Claude usage** (5h/7d windows with percentages and reset times) from `check-usage.sh` cache
– Collects **autonomous dev** stats (run number, last cost, exit code) from `state.json`
– POSTs assembled JSON to `https://pezant.ca/tools/dashboard/api/metrics` with Bearer auth
– Registered as PM2 cron job (`dashboard-push`, `*/5 * * * *`)
### 3. pezantTools Deployment
– Merged ~40 commits from `main` into VM’s `production` branch
– Brought dashboard view, routes, lib/dashboard.js, and auth module to production
– Resolved untracked file conflicts on VM (stash + clean + merge)
### 4. OAuth Return-to-Origin Fix
– `requireOAuth` middleware now saves `req.originalUrl` to `req.session.returnTo`
– OAuth callback reads `returnTo` from session instead of hardcoding `/tools/upload`
– Visiting `/dashboard` while logged out now correctly returns to `/dashboard` after Google login
## Technical Details
### Data Flow
“`
WSL (every 5 min) VM (pezant-tools)
┌──────────────────┐ HTTPS POST ┌─────────────────────┐
│ push-metrics.sh │ ──────────────→ │ /tools/dashboard/ │
│ • check-usage │ Bearer auth │ api/metrics │
│ • autonomousDev │ │ → dashboard- │
│ /state.json │ │ metrics.json │
└──────────────────┘ └─────────────────────┘
↓
┌─────────────────────┐
│ Dashboard EJS view │
│ • PM2 (live query) │
│ • System (live) │
│ • Claude usage │
│ • Autodev stats │
│ 30s auto-refresh │
└─────────────────────┘
“`
### Apache OIDC Ordering Lesson
`
### Files Changed
| File | Change |
|——|——–|
| `pezantTools/scripts/push-metrics.sh` | **New** — metrics collection + push |
| `pezantTools/lib/auth.js` | Added `returnTo` session save |
| `pezantTools/server.js` | OAuth callback reads `returnTo` |
| `pezantTools/CLAUDE.md` | Documented dashboard feature |
| `pezantTools/lib/dashboard.js` | Already existed, deployed to VM |
| `pezantTools/views/dashboard.ejs` | Already existed, deployed to VM |
| VM Apache config | Added `/dashboard` proxy + OIDC exemption |
### Commits
– `6f40984` — Add dashboard metrics push script
– `e89c7af` — Add live dashboard with PM2, system health, and metrics widgets
– `3be857c` — Fix datetime deprecation warning in push-metrics.sh
– `b99a213` — Document dashboard in CLAUDE.md
– `ab00b6d` — Redirect back to original URL after OAuth login
## What’s Not Wired Yet (v2)
– **Agent Journal widget** — needs Discord API read or local journal log file
– **Free Games widget** — needs aggregation from free-games-pipeline data
– **Uptime monitor** — `/tmp/uptime-monitor-state.json` on VM could feed a new widget
– **Git activity** — cross-repo commit/PR stats via `gh` CLI
– **Data staleness indicator** — `pushed_at` timestamp exists but not shown in UI
## Verification
– `pezant.ca/dashboard` → redirects to Google login → returns to dashboard after auth
– PM2 Services widget shows 21 processes with status/memory/uptime
– System Health shows disk/memory/load
– Claude Usage shows 36% (5h) and 36% (7d) with reset timers
– Autonomous Dev shows run #2, $3.01 cost
– Metrics push runs every 5 min via PM2 cron `dashboard-push`