# Pi Car Companion A local-first Raspberry Pi companion for the MG4. The Pi hosts a secure dashboard while the existing Android infotainment system remains the display and touch interface. The current MVP slice includes: - atomic first-run administrator creation with no default credentials; - Argon2id password hashing and revocable, hashed server-side sessions; - CSRF, trusted-origin, rate-limit, and secure-header protections; - SQLite persistence and append-oriented authentication audit events; - real host, CPU, memory, disk, network, uptime, and service status; - field-level unavailable states when host data cannot be collected; - authenticated Server-Sent Events for live status updates; - a responsive 1920×720-oriented setup, login, and dashboard UI; - an idempotent Raspberry Pi installer with systemd start-on-boot support; - atomic, dashboard-triggered Git updates with automatic verification and rollback safety; - automated API security tests and reproducible quality commands. Jobs, artifacts, the Android companion, and remaining operations work are tracked in [PLAN.md](./PLAN.md). ## Requirements - Node.js 22 - npm 10 or newer - Linux, macOS, or Windows for development Raspberry Pi OS Lite / Debian arm64 is the production target but has not yet been hardware-validated. ## Raspberry Pi installation On a clean Raspberry Pi OS or Debian installation: ```bash git clone https://git.molberg.cloud/alex/pi-car-companion.git cd pi-car-companion ./install.sh ``` The script asks for sudo access and then: - installs Node.js 22, Git, Avahi, SQLite, and native build requirements; - creates a dedicated `pi-companion` service account; - builds and verifies the server and dashboard; - installs an atomic release under `/opt/pi-car-companion`; - stores application data under `/var/lib/pi-car-companion`; - stores root-managed configuration under `/etc/pi-car-companion`; - enables the companion and Avahi services at boot; - starts the service and verifies `/healthz`. The installer prints the final dashboard address, normally `http://.local:8787`. Open it and create the first administrator account. `install.sh` is idempotent. After pulling changes in the original clone, run it again to deploy that checkout: ```bash git pull --ff-only ./install.sh ``` ## Dashboard updates Open **Settings** and select **Update now**. The Pi will: 1. fetch the configured branch from `origin`; 2. refuse non-fast-forward history changes; 3. create an isolated release worktree; 4. install dependencies and run script checks, lint, type checks, tests, and builds; 5. atomically activate the release only after every check passes; 6. restart the background service and verify its health endpoint; 7. automatically restore the previous release if startup verification fails. If any step fails, the current release stays active and Settings shows the failure. Updates use the Git credentials of the local user who ran `install.sh`; credentials are not copied into the web service or repository configuration. Non-interactive credentials such as an SSH deploy key or cached HTTPS credential work best. Useful service commands: ```bash sudo systemctl status pi-car-companion sudo journalctl -u pi-car-companion -n 100 --no-pager sudo journalctl -u pi-car-companion-update -n 100 --no-pager ``` ## Development Install dependencies: ```bash npm install ``` Start the API in one terminal: ```bash npm run dev ``` Start the Vite dashboard in another: ```bash npm run dev:web ``` Open `http://127.0.0.1:5173`. The development server proxies API requests to `http://127.0.0.1:8787`. Local development data is stored in `server/data/companion.db` and ignored by Git. ## Quality gate Run every host-runnable check: ```bash npm run check ``` This runs ESLint, strict TypeScript checks, tests, and both production builds. Audit production dependencies separately from development tooling: ```bash npm audit --omit=dev ``` ## Production-mode preview Build and start the combined server/dashboard: ```bash npm run build NODE_ENV=production \ DATABASE_PATH=./server/data/companion.db \ ALLOWED_ORIGINS=http://127.0.0.1:8787 \ npm start --workspace @pi-car/server ``` Then open `http://127.0.0.1:8787`. The development default remains loopback-only. `install.sh` explicitly enables LAN access so the car can reach the dashboard. ## Configuration See [.env.example](./.env.example). Configuration is validated at startup. Important values: - `HOST`: listen address, defaults to `127.0.0.1` - `PORT`: HTTP port, defaults to `8787` - `DATABASE_PATH`: SQLite database location - `SESSION_TTL_HOURS`: session lifetime, defaults to 24 hours - `COOKIE_SECURE`: enable for HTTPS deployments - `ALLOWED_ORIGINS`: comma-separated exact browser origins accepted for state changes - `UPDATE_STATUS_PATH`: update state shared with the systemd update unit - `VERSION_FILE`: revision metadata for the active atomic release ## Safety boundary This project does not modify the MG4 firmware, launcher, vehicle controls, CAN bus, or safety systems. It does not expose arbitrary shell commands, SSH, ADB, the Docker socket, or unrestricted filesystem access through the dashboard.