635a130f0b
Build and Push Docker Images / detect-changes (push) Successful in 11s
Build and Push Docker Images / build-auth-api (push) Successful in 1m0s
Build and Push Docker Images / build-employee-api (push) Successful in 1m2s
Build and Push Docker Images / build-transit-api (push) Successful in 1m1s
Build and Push Docker Images / build-error-log-api (push) Successful in 1m5s
Build and Push Docker Images / build-admin-ui (push) Successful in 1m13s
Build and Push Docker Images / build-monitoring-ui (push) Successful in 1m15s
Build and Push Docker Images / deploy-test-node (push) Successful in 3s
### Summary of Changes
1. Documentation Consolidation:
• Relocated the docs/ folder and all repository .md files (README.md, DEPLOYMENT.md, DOCKER_README.md,
DOMAINS_README.md, GETTING_STARTED.md, CI_CD_PORTAINER_GUIDE.md, ADMIN_DEPLOYMENT_SUMMARY.md,
SECURITY_PRIVATE_FILES.md, handoff.md, azure-project-plan.md, plus service-specific READMEs) into .
• Updated document links in README.md.
2. AI Agent Project Map:
• Created PROJECT_MAP.md in the project root containing complete architecture diagrams, service specs, ports, DB
schemas, environment variables, and developer workflows.
• Added PROJECT_MAP.md to .gitignore.
3. Monitoring UI & Infrastructure Integration:
• Added monitoring_ui service to docker-compose.yml (port 5175).
• Configured Gitea workflow docker-build.yml for monitoring_ui builds.
• Added CORS middleware headers in index.js.
• Added nginx.conf copy step in Dockerfile.
──────
### Recommended Commit Message
docs: consolidate project documentation into monitoring_ui and add agent project map
- Move all markdown documentation files and docs/ folder into monitoring_ui/docs/
- Update documentation hub index (monitoring_ui/docs/README.md) with relative paths
- Generate comprehensive AI agent reference map (PROJECT_MAP.md) in repository root
- Add PROJECT_MAP.md and monitoring_ui build output/env overrides to .gitignore
- Integrate monitoring_ui service into docker-compose.yml and Gitea CI workflow
- Configure CORS handling in employee_api for monitoring dashboard access
──────
### Alternative Short Commit Message
refactor(docs): move docs to monitoring_ui and create AI agent PROJECT_MAP.md
282 lines
13 KiB
Markdown
282 lines
13 KiB
Markdown
# Transit Control Room
|
|
|
|
`monitoring_ui` is a React + Vite operations dashboard for the XTransit service group. It gives an operator one place to answer four questions:
|
|
|
|
1. Are the services reachable right now?
|
|
2. What kind of data does each service provide?
|
|
3. Which errors and bad requests have been recorded?
|
|
4. Can I safely inspect a real API response without building a curl command by hand?
|
|
|
|
The dashboard is a browser-only application. It does not introduce a database, server-side session store, or monitoring proxy. Requests go directly from the browser to the configured services.
|
|
|
|
## 1. What It Monitors
|
|
|
|
| Surface | Default URL | Health request | Purpose |
|
|
| ------------- | -------------------------------------------- | -------------- | --------------------------------------------------------- |
|
|
| Auth API | `http://localhost:5000` | `GET /me` | Login, JWT sessions, and current-user information |
|
|
| Employee API | `https://employees.xtransit.testinstance.nl` | `GET /health` | Employee onboarding and employee records |
|
|
| Transit API | `http://localhost:5001` | `GET /health` | Schedules, routes, GPS, fleet, and administration |
|
|
| Error Log API | `http://localhost:5003` | `GET /health` | Centralized service errors and bad requests |
|
|
| Admin UI | `http://localhost:5174` | `GET /health` | Availability of the deployed React administration console |
|
|
|
|
The URLs are development defaults only. For a deployed dashboard, use the Connections screen or build-time `VITE_*` variables.
|
|
|
|
### Health semantics
|
|
|
|
- `healthy`: the request returned a successful HTTP status.
|
|
- `degraded`: the service answered, but returned a non-success status such as `401`, `403`, or `503`.
|
|
- `offline`: the browser could not establish a response, usually because the service is stopped, the URL is wrong, TLS failed, or CORS blocked the request.
|
|
- `checking`: the first poll has not completed yet.
|
|
|
|
The Auth API uses `/me` because it does not currently expose a public `/health` endpoint. Without a JWT this normally appears as `degraded`, not as a broken service. Add a token in Connections when an authenticated Auth API signal is required.
|
|
|
|
Transit health includes database reachability. Employee health currently confirms process reachability only. Admin UI health is supplied by the nginx configuration in `admin_ui/nginx.conf` and returns a small JSON document.
|
|
|
|
## 2. Features
|
|
|
|
### Overview
|
|
|
|
The Overview tab contains one card per monitored surface. Each card shows:
|
|
|
|
- current status;
|
|
- response time for the latest poll;
|
|
- a compact latency history from recent polls;
|
|
- the returned health payload.
|
|
|
|
The top-level pulse shows how many surfaces are healthy and the average latency across completed checks. Polling can be set to 15 seconds, 30 seconds, or one minute.
|
|
|
|
### Service catalog
|
|
|
|
The Service catalog is a human-readable map of the data each service serves. It is deliberately maintained as a small allowlisted catalog rather than attempting to discover every Express route at runtime. This keeps the dashboard understandable and avoids exposing internal routes or implementation details.
|
|
|
|
### Errors and bad requests
|
|
|
|
The Errors & bad requests tab reads:
|
|
|
|
```text
|
|
GET /error_log?limit=80
|
|
Authorization: Bearer <admin-jwt>
|
|
```
|
|
|
|
The Error Log API restricts this endpoint to administrator tokens. The dashboard displays timestamp, service, route or sub-service, and normalized error text. The dashboard does not write new logs itself; the existing APIs already report their failures to `error_log_api`.
|
|
|
|
If the token is missing, the dashboard explains how to configure it. If the token is expired or not an administrator token, the API response is shown as a load failure rather than silently displaying an empty incident list.
|
|
|
|
### Request lab
|
|
|
|
The Request lab executes only known routes listed in `testerRoutes` inside `monitoring_ui/src/App.jsx`. It supports representative calls for:
|
|
|
|
- Auth API current-session inspection;
|
|
- Employee API health;
|
|
- Transit API health;
|
|
- public schedule progress;
|
|
- driver daily schedule;
|
|
- recent Error Log API entries.
|
|
|
|
The selected service, method, and path determine the destination. An optional JSON body can be entered for future write routes. Non-GET requests require a browser confirmation before execution.
|
|
|
|
This is an operator diagnostic tool, not a general-purpose arbitrary URL proxy. Keep the allowlist intentionally narrow when adding routes.
|
|
|
|
### Connections
|
|
|
|
The Connections tab edits the five service base URLs and the optional admin JWT. Values are stored in `localStorage` under:
|
|
|
|
- `transit-monitor-urls`
|
|
- `transit-monitor-token`
|
|
|
|
This makes local experimentation convenient, but it also means the token is readable by JavaScript running on the same origin. Use the dashboard only in a trusted browser profile and do not use it on a shared workstation with untrusted browser extensions.
|
|
|
|
## 3. Local Development
|
|
|
|
```bash
|
|
cd monitoring_ui
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
Open the URL printed by Vite, normally `http://localhost:5173`.
|
|
|
|
Build and preview the production bundle:
|
|
|
|
```bash
|
|
npm run build
|
|
npm run preview
|
|
```
|
|
|
|
The app uses React 18 and Vite 5, matching the existing admin UI's frontend generation approach. Its main files are:
|
|
|
|
```text
|
|
monitoring_ui/
|
|
├── index.html browser entry point
|
|
├── package.json scripts and dependencies
|
|
├── vite.config.mjs Vite React configuration
|
|
├── src/
|
|
│ ├── main.jsx React bootstrap
|
|
│ ├── App.jsx service model, polling, tabs, request lab
|
|
│ └── styles.css responsive control-room styling
|
|
└── README.md short navigation pointer
|
|
```
|
|
|
|
## 4. Configuration
|
|
|
|
### Build-time environment variables
|
|
|
|
Create `monitoring_ui/.env.local` for a deployed or non-default environment:
|
|
|
|
```env
|
|
VITE_AUTH_API=https://auth.example.test
|
|
VITE_EMPLOYEE_API=https://employees.xtransit.testinstance.nl
|
|
VITE_TRANSIT_API=https://transit.example.test
|
|
VITE_ERROR_LOG_API=https://error.example.test
|
|
VITE_ADMIN_UI=https://admin.example.test
|
|
```
|
|
|
|
Vite reads these variables when the app is built. They are not secrets. Do not put JWTs, database passwords, signing keys, or API credentials in `.env.local` values that will be shipped to the browser.
|
|
|
|
The Connections screen is useful when the same build needs to point at different environments. Its values override the initial defaults in the current browser only.
|
|
|
|
### CORS requirements
|
|
|
|
Because the dashboard calls services directly, every monitored API must allow the dashboard origin. The existing Auth, Transit, and Error Log services already expose permissive CORS middleware. Employee API has matching browser CORS middleware in `employee_api/index.js`.
|
|
|
|
For production, replace wildcard CORS with an explicit dashboard origin where practical. At minimum, allow:
|
|
|
|
- `GET`, `POST`, `OPTIONS`, and any methods used by approved tester routes;
|
|
- `Content-Type`;
|
|
- `Authorization`.
|
|
|
|
If the browser console reports a refused connection but direct `curl` succeeds, check CORS before changing the dashboard code.
|
|
|
|
## 5. Authentication and Security
|
|
|
|
The dashboard does not implement a second login system. It accepts a JWT created by the existing Auth API. Obtain a token through the normal admin login flow, then paste it into Connections.
|
|
|
|
The Error Log API verifies both JWT validity and the `isAdmin` claim. A valid non-admin token is not sufficient to read centralized errors.
|
|
|
|
Operational safeguards:
|
|
|
|
- never commit `.env.local` or copied tokens;
|
|
- avoid putting production JWTs in screenshots, issue reports, or browser history;
|
|
- keep the request lab allowlist small;
|
|
- require confirmation for all mutating requests;
|
|
- prefer read-only routes for routine diagnostics;
|
|
- use HTTPS for deployed APIs and dashboard access;
|
|
- restrict CORS to known origins in production;
|
|
- consider moving token handling to an authenticated same-origin backend if the dashboard becomes a multi-user production console.
|
|
|
|
## 6. Deployment Options
|
|
|
|
### Static hosting
|
|
|
|
The dashboard can be hosted as static files from any web server that supports SPA fallback to `index.html`. Build it with:
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
Publish `monitoring_ui/dist`. Configure the web server to serve `index.html` for unknown application paths. The current dashboard uses client-side tab state and does not require route rewrites beyond the root page, but SPA fallback remains a sensible default.
|
|
|
|
### Container hosting
|
|
|
|
The repository includes a Node build stage followed by nginx in `monitoring_ui/Dockerfile`. Runtime configuration is written to `env-config.js` by `monitoring_ui/docker-entrypoint.sh`, so the same image can be promoted between environments without baking service URLs into the JavaScript bundle.
|
|
|
|
The root Compose stack deploys this image as `monitoring_ui` on host port 5175. Set these Compose variables when deploying:
|
|
|
|
```env
|
|
AUTH_API=https://auth.xtransit.testinstance.nl
|
|
EMPLOYEE_API=https://employees.xtransit.testinstance.nl
|
|
TRANSIT_API=https://transit.xtransit.testinstance.nl
|
|
ERROR_LOG_API=https://error.xtransit.testinstance.nl
|
|
ADMIN_UI=https://admin.xtransit.testinstance.nl
|
|
```
|
|
|
|
The Gitea workflow detects changes under `monitoring_ui/**`, builds `monitoring_ui/Dockerfile`, and pushes the image as `monitoring_ui:<branch>` and `monitoring_ui:<commit>`. The `dev` branch includes the image in the Portainer redeploy dependency chain.
|
|
|
|
### Reverse proxy
|
|
|
|
A reverse proxy can place the dashboard and service domains behind one TLS boundary. This is often preferable for production because it simplifies CORS and gives operators a single origin. It is not required for local development.
|
|
|
|
## 7. Troubleshooting
|
|
|
|
### All cards show offline
|
|
|
|
1. Check that the API processes are running.
|
|
2. Check the URL in Connections, including protocol and port.
|
|
3. Open the health URL directly in a browser or use `curl`.
|
|
4. Inspect the browser console for CORS or TLS errors.
|
|
5. Confirm that Docker port mappings match `docker-compose.yml`.
|
|
|
|
### Auth API shows degraded
|
|
|
|
`GET /me` requires a bearer token. Paste a current admin JWT into Connections. A `401` means the API answered and is reachable, but the supplied token is absent or invalid.
|
|
|
|
### Error list is empty
|
|
|
|
An empty list can mean either that no errors were returned or that the request was not authorized. Check the Errors tab status text and verify that the token has `isAdmin: true`. The Error Log API also requires its database table `data.errors` to exist.
|
|
|
|
### Employee API cannot be called from the dashboard
|
|
|
|
Check that the deployed image includes the CORS middleware from `employee_api/index.js`. A stale container image may still be running an earlier version.
|
|
|
|
### Admin UI health fails
|
|
|
|
Rebuild the admin UI image after adding `admin_ui/nginx.conf`. The endpoint is:
|
|
|
|
```bash
|
|
curl -i http://localhost:5174/health
|
|
```
|
|
|
|
Expected body:
|
|
|
|
```json
|
|
{ "status": "ok", "service": "admin_ui" }
|
|
```
|
|
|
|
### Health is slow
|
|
|
|
The dashboard measures full browser request time, including DNS, TLS, network, and API processing. Compare the dashboard value with a server-side curl from the same network before diagnosing application latency.
|
|
|
|
## 8. Extending the Dashboard
|
|
|
|
To add a service:
|
|
|
|
1. Add its base URL to `configured`.
|
|
2. Add its metadata to `serviceMeta`.
|
|
3. Add a health path to `healthPaths`.
|
|
4. Add representative safe routes to `testerRoutes`.
|
|
5. Add its environment variable to this document and `.env.local` examples.
|
|
6. Confirm the service has CORS headers and an appropriate health endpoint.
|
|
7. Run `npm run build` and perform a browser smoke test.
|
|
|
|
To add a request route, include a short label and keep the route literal. Avoid user-entered arbitrary URLs, unrestricted HTTP methods, or unrestricted request headers.
|
|
|
|
Useful future extensions include:
|
|
|
|
- a time-window chart backed by a real metrics store;
|
|
- service version/build information in health payloads;
|
|
- threshold-based alerts for latency and repeated failures;
|
|
- export of incident rows for an operator handoff;
|
|
- a same-origin authenticated backend if the tool becomes a shared production console;
|
|
- a dedicated `/health` endpoint for Auth API so authentication status and process health are separate signals.
|
|
|
|
## 9. Validation Checklist
|
|
|
|
Before shipping a dashboard change:
|
|
|
|
```bash
|
|
cd monitoring_ui
|
|
npm install
|
|
npm run build
|
|
```
|
|
|
|
Then verify in a browser:
|
|
|
|
- all five cards render;
|
|
- one healthy local service shows a payload and latency;
|
|
- an unavailable service is clearly marked offline;
|
|
- Connections persists URL changes after reload;
|
|
- an admin JWT loads Error Log API data;
|
|
- an invalid token produces a visible error state;
|
|
- each Request lab route targets the expected service;
|
|
- the layout remains usable at a narrow mobile width.
|