# Transit Project This repository contains a suite of Node.js microservices, a modern React administration console, an operational monitoring dashboard, and a legacy client retained for compatibility reference. - `auth_api` — Authentication and token issuance (default port 5000) - `employee_api` — Employee onboarding and management (default port 4000) - `transit_api` — Routes, schedules, fleet, GPS, and transit administration (default port 5001) - `error_log_api` — Centralized error logging and viewer (default port 5003) The error API is available at `https://error.xtransit.testinstance.nl`. - `admin_ui` — React + Vite administration interface The admin panel is available at `https://admin.xtransit.testinstance.nl`. - `monitoring_ui` — React + Vite service monitoring dashboard The monitoring dashboard is available at host port 5175 (`https://monitor.xtransit.testinstance.nl` or local port 5173). - `windows_xp_driver_ui/` — Native Win32 driver client targeting Windows XP-era systems - `deprecated/` — Legacy Flutter bus terminal, retained for reference while moving the client to a Windows XP-era build path The repository also includes CI workflows that build Docker images and push them to GitHub Container Registry (GHCR). See [monitoring_ui/docs/DOMAINS_README.md](monitoring_ui/docs/DOMAINS_README.md) for the central list of all public domains and their functions. The consolidated documentation hub is available in [monitoring_ui/docs/README.md](monitoring_ui/docs/README.md). Important: this README does not contain any passwords or other sensitive information. Always store secrets outside of version control (environment variables, secret managers, Portainer secrets, etc.). --- ## Security & Private Files **⚠️ Important:** This repository excludes private documentation and setup instructions from Git and Docker builds. See [monitoring_ui/docs/SECURITY_PRIVATE_FILES.md](monitoring_ui/docs/SECURITY_PRIVATE_FILES.md) for details on: - What files are kept private and why - How `.gitignore` and `.dockerignore` protect sensitive information - Best practices for handling deployment documentation - Guidelines for adding new private files **Private files are excluded** (not in git/docker): - `GETTING_STARTED.md` - Internal setup guide - `ADMIN_DEPLOYMENT_SUMMARY.md` - Deployment status - `CI_CD_PORTAINER_GUIDE.md` - Infrastructure docs - `DEPLOYMENT.md` - Deployment procedures - Custom instruction files (`.instructions.md`, etc.) --- ## Table of Contents / Directory Overview - `auth_api/` — Source code for the authentication service - `employee_api/` — Source code for the employee service - `transit_api/` — Source code for the transit service - `error_log_api/` — Source code for centralized error collection - `admin_ui/` — Source code for React admin panel - `monitoring_ui/` — Source code for React monitoring dashboard and documentation hub - `windows_xp_driver_ui/` — Native driver interface - `deprecated/` — Legacy client reference - `.github/workflows/docker-build.yml` — CI: build and push images to GHCR - `docker-compose.yml` — Compose file that pulls images from GHCR or builds locally and connects to an external PostgreSQL database - `.env.example` — Example environment variables - `monitoring_ui/docs/` — Consolidated documentation hub --- ## Prerequisites - Git - Docker (20.10+) - Docker Compose (v2+ or `docker compose`) - (Optional) A remote environment running Portainer - (Optional) A GitHub account with permissions to publish images to GHCR --- ## Security — Important Reminders - Never commit secrets into git. Use a local `.env` file (kept in `.gitignore`) or a secret manager. - JWT secrets, database passwords, and other credentials must be supplied via environment variables or Portainer secrets. --- ## Environment Variables (Example) Your `docker-compose.yml` expects environment variables defining the database connection and JWT secret. Create a local `.env` file in the project root (DO NOT commit). Use these variables as a guide: ```env # Database (external Postgres) POSTGRES_HOST=your.db.host.or.ip POSTGRES_PORT=5432 POSTGRES_DB=transit_db # Per-service DB credentials (optional: you can also use a single DB user per DB) POSTGRES_USER_AUTH=auth_user POSTGRES_PASSWORD_AUTH=strong_password_auth POSTGRES_USER_EMPLOYEE=employee_user POSTGRES_PASSWORD_EMPLOYEE=strong_password_employee POSTGRES_USER_TRANSIT=transit_user POSTGRES_PASSWORD_TRANSIT=strong_password_transit POSTGRES_USER_ERROR_LOG=error_logger POSTGRES_PASSWORD_ERROR_LOG=strong_password_error_log # JWT secret for services using JWT JWT_SECRET=super_secret_jwt_key_here # Optional: central error log endpoint for clients/services ERROR_LOG_API_URL=https://error.xtransit.testinstance.nl/error_log ``` Note: The exact variables are read by `docker-compose.yml`. Adjust names and values according to your environment. --- ## Local Development (Without Docker) 1. Ensure you have a running PostgreSQL instance (local or remote). 2. Copy a `.env` file for each API or export the required environment variables. Example: running `auth_api` locally: ```bash cd auth_api # Install dependencies npm install # Export env vars (example): export DB_HOST=your.db.host export DB_PORT=5432 export DB_NAME=transit_db export DB_USER=auth_user export DB_PASSWORD=... export JWT_SECRET=... npm start ``` Repeat for `employee_api`, `transit_api`, and `error_log_api` with the appropriate env keys and ports. Tip: During development, you can use a single Postgres instance and configure schemas and roles. --- ## Docker / Portainer — Deployment (With External Postgres) This repository includes a `docker-compose.yml` file that pulls images from GHCR. The compose setup is configured to use an external Postgres instance. Before starting: - Ensure your `.env` file with database credentials and `JWT_SECRET` is prepared on the server. - Ensure the host running compose has network connectivity to the Postgres host. Deployment steps (server / Portainer host): ```bash # 1. Place .env on the server (NOT in git) scp .env user@server:/path/to/project/.env # or create it directly on the server # 2. Login to GHCR (to pull private images) # Username = your GitHub username # Password = PAT with 'write:packages'/'read:packages' scopes or your GITHUB_TOKEN docker login ghcr.io # 3. Start stack docker-compose --env-file .env up -d # or with compose V2: docker compose --env-file .env up -d ``` If using Portainer, you can also paste `docker-compose.yml` as a "Stack" in the Portainer UI and deploy via the UI. Add environment variables in Portainer or reference a server-side `.env`. Note on `depends_on` in `docker-compose.yml`: because you are using an external DB, compose configs sometimes reference a non-existent `db` service. You can safely remove or ignore those `depends_on` rules, as long as your database is available before the services attempt to connect. --- ## GitHub Actions & Container Registry (CI) The project includes a CI workflow in `.github/workflows/docker-build.yml` (and `.gitea/workflows/docker-build.yml`) that executes the following steps on push to `main`/`dev`: - Checkout repository - Build Docker images for each API (using BuildKit / Buildx) - Login to the Container Registry (GHCR) and push images - Generate tags (`latest`, branch/sha, semver if present) To use GHCR on your server: 1. Create a Personal Access Token (PAT) with `read:packages` (and `write:packages` if you also wish to push). 2. Login on the server: `docker login ghcr.io` (use PAT as password). Example image name: ``` ghcr.io///auth_api:latest ``` --- ## Health Checks, Endpoints, and Debugging Useful endpoints (example): - `GET /health` — (available in `employee_api`, `transit_api`, `error_log_api`) checks reachability - `POST /login` — (`auth_api`) authentication - `GET /schedule/daily?date=YYYY-MM-DD` — (`transit_api`) requires authentication Viewing logs: ```bash # Logs from a service docker-compose logs -f auth_api # Or via container ID docker logs -f auth_api ``` Troubleshooting DB connection: - Verify network connectivity to `POSTGRES_HOST` - Check users and permissions in Postgres - Ensure the expected schema (such as `workers` or `transit`) exists if queries expect it --- ## Common Tasks & Commands ```bash # Build & run (pull images from GHCR) docker-compose --env-file .env up -d # Pull latest images docker-compose pull # Recreate containers docker-compose up -d --force-recreate # Stop and remove containers docker-compose down # Login to GHCR docker login ghcr.io ``` --- ## Migrations & Database Schema Database schemas and migrations are maintained separately. Ensure you: - Create the necessary schemas (`workers`, `transit`, `data`, etc.) - Configure users and privileges for the respective services ### Error Logging Schema For centralized error logging, create schema `data` and table `data.errors`: ```sql CREATE SCHEMA IF NOT EXISTS data; CREATE TABLE IF NOT EXISTS data.errors ( id BIGSERIAL PRIMARY KEY, "date" TIMESTAMPTZ NOT NULL DEFAULT NOW(), "service" TEXT NOT NULL, partofservice TEXT, error TEXT NOT NULL ); ``` Use a dedicated user with minimal privileges, e.g. `error_logger`: ```sql CREATE ROLE error_logger LOGIN PASSWORD 'strong_password_error_log'; GRANT USAGE ON SCHEMA data TO error_logger; GRANT INSERT, SELECT ON data.errors TO error_logger; ``` If you do not have a database yet, you can run a local PostgreSQL container for development: ```bash docker run --name transit-db -e POSTGRES_DB=transit_db -e POSTGRES_USER=transit_user -e POSTGRES_PASSWORD=pass -p 5432:5432 -d postgres:15-alpine ``` For production / Portainer setups, follow your infrastructure policy and use a managed database or secured host. --- ## Deployment Tips - Use distinct database users per service with minimal privileges - Use secrets in Portainer, Docker swarm, or Kubernetes in production - Use a reverse proxy (Nginx, Traefik) for TLS/HTTPS - Set up log aggregation and monitoring (Prometheus/Grafana, ELK, etc.) --- ## Contributing - Create feature branches and open pull requests - Push to `dev` or `main` depending on your branching policy - CI will automatically build and push images for `main`/`dev` --- ## Where to Find Everything - API code: `auth_api/`, `employee_api/`, `transit_api/`, `error_log_api/` - Frontend UI: `admin_ui/`, `monitoring_ui/` - Documentation hub: `monitoring_ui/docs/` - CI workflows: `.github/workflows/docker-build.yml`, `.gitea/workflows/docker-build.yml` --- ## Admin Control Center The project includes a **modern React admin dashboard** for fleet and schedule management. ### Features - **Fleet Management**: Create and manage buses with seat capacity and license plates - **Transit Lines**: Define bus routes with start/end stops and duration - **Route Management**: Link stops to bus lines with drag-and-drop reordering - **Schedule Maker**: Create schedules by assigning vehicles and crew to bus lines with time slots - **Timetable View**: 24-hour timetable showing scheduled services - **Delete Operations**: Remove stops, lines, and schedules with confirmation modals ### Admin UI Location ``` admin_ui/ ├── src/ │ ├── components/ │ │ ├── StopsManager.jsx # Create and manage transit stops │ │ ├── BusLinesManager.jsx # Manage bus lines and routes │ │ ├── FleetManager.jsx # Manage fleet vehicles │ │ ├── LinkStop.jsx # Drag-drop route stop assignment │ │ ├── ScheduleMaker.jsx # Create and manage schedules │ │ ├── TimetableViewer.jsx # Public timetable (reusable) │ │ └── Login.jsx # Admin authentication │ ├── App.jsx # Main app component │ ├── api.js # API client with runtime config │ └── styles.css # Responsive UI styling ├── docker-entrypoint.sh # Runtime env config └── Dockerfile # Multi-stage build ``` ### Building the Admin UI ```bash cd admin_ui npm install npm run build # Production build npm run dev # Development (Vite) ``` ### Docker Deployment The admin UI is included in `docker-compose.yml` as service `admin_ui` on port 5174. ```bash docker-compose up admin_ui # Access at http://localhost:5174 ``` ### Public Schedule API The Transit API exposes public (unauthenticated) schedule endpoints: **Endpoints:** - `GET /schedules?date=YYYY-MM-DD&lineId=ID` — Get schedules for a date/line - `GET /schedules/:scheduleId` — Get schedule details - `GET /schedules/:scheduleId/stops` — Get stops on a schedule's line **Example:** ```bash curl https://transit.xtransit.testinstance.nl/schedules?date=2026-05-06 ``` **TimetableViewer Component:** ```jsx import TimetableViewer from "./components/TimetableViewer"; ; ``` ### Schedule Maker Documentation See [monitoring_ui/docs/admin_ui/SCHEDULE_API.md](monitoring_ui/docs/admin_ui/SCHEDULE_API.md) for detailed API documentation, usage examples, and UI features. --- ## Authentication Admin dashboard uses simple JWT-based authentication: 1. **Login** with user code (e.g., `42`) 2. Receive JWT token from `auth_api` 3. Use token for admin operations (`/admin/*` endpoints) Admin authorization is controlled by `ADMIN_USER_CODES` environment variable configured in the `auth_api` service: ```bash # Set admin user codes for the auth service (comma-separated) ADMIN_USER_CODES=42,101,205 ``` --- ## Development vs Production ### Development Mode Use `DEV_MOCK=1` to work without a database (in-memory mock storage): ```bash # For local development set admin codes on the auth_api and start services ADMIN_USER_CODES=42 DEV_MOCK=1 JWT_SECRET=devsecret npm --prefix ./auth_api start ``` ### Production Mode Set up real PostgreSQL database and provide credentials via environment variables.