# Infrastructure Monitoring Dashboard ## Project Overview A web-based status feed aggregator for a K-12 school district IT department. Provides a single-pane-of-glass view of vendor service health, replacing the need to manually check multiple status pages during incidents. ## Target Vendors | Vendor | Type | Status Source | |---|---|---| | Microsoft 365 | Productivity suite | Service Communications API (Graph API) | | SpamTitan | Email security | Synthetic check — district appliance (mailportal.nhsd.net) | | PowerSchool | Student Information System | Atlassian Statuspage API (status.powerschool.com) | | Classlink | SSO / Identity | Atlassian Statuspage API (status.classlink.com) | | Apple | Device ecosystem | Apple System Status JSON feed | | DRC | Assessment / Testing | Synthetic check — PA INSIGHT portal (status page is JS-rendered Angular app) | | FinalSite | School website CMS | Atlassian Statuspage API (status.finalsite.com) | | Google Workspace | Productivity suite | Google Workspace Status Dashboard JSON feed | | Follett | Library management | Synthetic check — district Destiny instance (northhills.follettdestiny.com) | | EdInsight | Data analytics (Harris Education Solutions) | Synthetic check — no public status page found | | Raptor | Visitor management | Status.io API (status.raptortech.com) | | SchoolMessenger | Communication platform | Atlassian Statuspage API (PowerSchool status page, SchoolMessenger components filtered) | | McGraw Hill | Curriculum / assessment | Synthetic check — ConnectED portal (status.mcgrawhill.com is JS-rendered) | | Fortinet | Network security | Atlassian Statuspage API (FortiGate Cloud — status.fortigate.forticloud.com) | | SherpaDesk | Helpdesk / ticketing | Synthetic check — app portal (no public status API) | | Study Island | Instructional practice | Atlassian Statuspage API (Edmentum — status.edmentum.com, Study Island component filtered) | | Classkick | Classroom assessment | Synthetic check — app portal (StatusCast API requires auth token) | | ClassDojo | Classroom communication | Synthetic check — app portal (no machine-readable status feed) | | Savvas K-12 | Curriculum / learning platform | Atlassian Statuspage API (status.savvas.com) | | Amazon AWS | Cloud infrastructure | RSS feed polling (EC2 us-east-1/2, S3, CloudFront, Route 53) | | Cloudflare | CDN / DNS | Atlassian Statuspage API (cloudflarestatus.com) | | SmartPass | Hall pass management | Instatus JSON API (smartpass.instatus.com) | | School Dismissal Manager | Dismissal management | Synthetic check — admin portal (status page redirects to StatusGator) | | Promethean | Interactive displays | Synthetic check — prometheanworld.com (panels used in standalone mode; no cloud features) | | RAZ-Kids | Reading platform | Synthetic check — Learning A-Z login portal (browser UA required; behind Cloudflare bot detection) | | Internet | Connectivity | TCP check to 8.8.8.8:53 | Note: Exchange Online is intentionally excluded — it is a component of M365 Service Health and would be redundant. New vendors should be added incrementally, not speculatively. ## FortiGate Dashboard Features In addition to the vendor status cards, the dashboard includes two FortiGate-specific panels that sit above the vendor grid: ### WAN Throughput Graph - Two side-by-side canvas graphs, one per WAN link (Crown Castle on port25, Comcast on port8) - Polls `GET /api/v2/monitor/system/interface` on the FortiGate every 30 seconds - Computes Mbps from cumulative byte counter deltas - Stores a 30-minute rolling history (60 points at 30s intervals) - Frontend fetches `/api/throughput` and renders using HTML5 Canvas ### FortiGate Health Card - Shows hostname, firmware version, uptime, CPU %, and memory % - Polls `GET /api/v2/monitor/system/status` and `GET /api/v2/monitor/system/resource/usage` - Updates every 2 minutes - CPU/memory values turn amber at ≥75% and red at ≥90% - Frontend fetches `/api/fortigate-health` Both panels use the built-in Node.js `https` module with `rejectUnauthorized: false` to handle the FortiGate's self-signed management certificate. ## Credentials / Environment `backend/.env` is gitignored and contains: - `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET` — Microsoft 365 Graph API - `FORTIGATE_HOST`, `FORTIGATE_API_TOKEN` — FortiGate REST API - `FORTIGATE_WAN1_INTERFACE`, `FORTIGATE_WAN1_LABEL` — Crown Castle WAN (port25) - `FORTIGATE_WAN2_INTERFACE`, `FORTIGATE_WAN2_LABEL` — Comcast WAN (port8) ## Hosting - **Web server**: Caddy - **URL**: https://status.nhsd.net:8443 (port 8443 to avoid conflict with existing Caddy instance on this machine) - **Access**: Local network only (DNS A record points to the host machine) - **TLS**: Caddy internal TLS (self-signed). IT staff only — browser cert warnings are acceptable. - **Important**: There is a separate, pre-existing Caddy instance already running on this machine (unrelated to this project). This project runs its own dedicated Caddy instance using `config/Caddyfile`. Do not confuse the two — always start/stop the dashboard Caddy explicitly with that Caddyfile. ## Architecture - **Frontend**: HTML/CSS/JS dashboard — lightweight, no heavy framework. Designed to work on a wall-mounted monitor or quick browser check. - **Backend**: Node.js service that polls vendor status on a schedule and caches results. - **Web server**: Caddy reverse-proxies to the backend API and serves the static frontend. - **Services**: NSSM runs both Caddy and the Node backend as Windows services. - **Data flow**: Backend polls vendors → caches to local store → frontend fetches from backend API → auto-refreshes on interval. ## API Endpoints | Endpoint | Description | Poll interval | |---|---|---| | `GET /api/status` | All vendor status cards | 2 minutes | | `GET /api/throughput` | WAN throughput history (60 points) | 30 seconds | | `GET /api/fortigate-health` | FortiGate system health | 2 minutes | | `GET /api/health` | Backend liveness check | On demand | ## Directory Structure ``` infrastructure-monitoring-dashboard/ ├── CLAUDE.md ├── README.md ├── .gitignore ├── bin/ │ ├── caddy/ # Drop caddy.exe here (git-ignored) │ └── nssm/ # Drop nssm.exe here (git-ignored) ├── config/ │ └── Caddyfile # Caddy server configuration ├── frontend/ │ ├── index.html │ ├── css/style.css │ └── js/app.js ├── backend/ │ ├── package.json │ ├── server.js │ ├── fortigate-throughput.js # WAN throughput poller │ ├── fortigate-health.js # FortiGate system health poller │ └── providers/ # One module per vendor └── scripts/ # NSSM service install/uninstall helpers ``` ## Design Principles - Keep it simple. This is a status board, not a monitoring platform. - Degrade gracefully — if a vendor check fails, show "unknown" rather than crashing. - Each vendor integration should be a self-contained module so they can be added/removed independently. - Optimize for glanceability — status should be obvious from across the room (color-coded, large indicators).