# Project Overview **Name**: Veridian Edge Agent **Type**: Edge computing service (sensor data sync) **Primary Languages**: TypeScript (Bun runtime) **Status**: v1.0.0, Production ## High-Level Description Veridian Edge is a SensorPush integration agent that runs on Raspberry Pi or Ubuntu. It polls the SensorPush Cloud API for environmental readings and syncs them to the Veridian backend API. **Architecture:** ``` SensorPush Cloud API → Veridian Edge Agent → Veridian Backend API ↓ SQLite (offline buffer) ``` **External Systems:** - SensorPush Cloud API (OAuth 2.0, automatic token refresh) - Veridian Backend API (HTTP/JSON webhooks) - Local SQLite database (offline resilience) - Systemd service management on Linux ## Multi-Repo Architecture This repo works in conjunction with **veridian** as a single codebase: - **veridian-edge** (this repo): Edge agent that polls SensorPush and syncs to backend - **veridian**: Main platform backend that receives data from edge agent When making changes, consider: - API contract: Edge agent must send data in format expected by Veridian backend - Authentication: API key authentication with Veridian backend - Error handling: Network failures must be buffered to SQLite ## Layout ``` veridian-edge/ ├── src/ # Source code │ ├── index.ts # Main entry point │ ├── sensorpush.ts # SensorPush API client │ ├── sync.ts # Sync logic to Veridian backend │ └── db.ts # SQLite database operations ├── scripts/ # Installation and maintenance scripts │ └── install.sh # Systemd service installer ├── config.json # Configuration (after installation) └── package.json # Bun dependencies ``` ## Conventions ### Language/Style - **TypeScript strict mode** enabled - **Bun runtime** (not Node.js) - **Hono framework** for HTTP endpoints - **Better-sqlite3** for local database - **Systemd service** for process management ### Package Manager - **Use `bun` exclusively** (this is a Bun project) - Commands: `bun install`, `bun run`, `bun test`, `bun add` ### Error Handling - Graceful degradation: Network failures buffer to SQLite - Retry logic with exponential backoff for API calls - Clear error messages in logs - Never expose credentials in logs ### Logging - Structured logging to systemd journal - Log levels: error, warn, info, debug - Include timestamp, severity, and context ### Config - Configuration file: `/opt/veridian-edge/config.json` - Sensitive data: email, password, API keys - Use `config.demo.json` or `config.example.json` as templates ## Patterns & Playbooks ### How to Add New Sensor Types 1. Update SensorPush API client to handle new sensor data 2. Add database schema migration if needed 3. Update sync logic to include new data type in API payload 4. Add tests for new sensor type 5. Update configuration schema ### How to Modify API Payload Format **WARNING**: This affects the Veridian backend integration. 1. Check Veridian backend API contract in `veridian/` repo 2. Update this repo's sync logic 3. Coordinate changes with Veridian backend deployment 4. Test with actual Veridian backend before deploying 5. Consider backward compatibility during transition ### How to Run Locally (Development) ```bash bun install cp config.demo.json config.json # Edit config.json with your credentials bun run dev ``` ### How to Run in Production (Raspberry Pi/Ubuntu) ```bash # Run installer (sets up systemd service) sudo ./scripts/install.sh # Service management sudo systemctl start veridian-edge sudo systemctl status veridian-edge sudo systemctl stop veridian-edge journalctl -u veridian-edge -f ``` ### Important Configuration Fields - `facilityId`: UUID of facility in Veridian backend - `backendUrl`: Veridian backend API URL - `backendApiKey`: API key for Veridian authentication - `sensorpush.email`: SensorPush account email - `sensorpush.password`: SensorPush account password - `sensorMappings`: Array mapping sensor IDs to room IDs ## PR & Learning Workflow - When a PR introduces a new pattern or fixes a subtle issue: 1. Summarize the lesson in 1-2 bullets 2. Append under "Patterns & Playbooks" above 3. Consider updating README.md if user-facing ## Testing Strategy - **Unit tests**: Bun test for pure functions - **Integration tests**: Mock SensorPush API and Veridian backend - **VPS verification**: Deploy to edge device and verify: - Service is running: `systemctl status veridian-edge` - Logs show successful sync: `journalctl -u veridian-edge -f` - Data appears in Veridian backend ## Deployment Considerations - **Target devices**: Raspberry Pi 4 (2GB+ RAM) or Ubuntu 22.04+ - **Installer script**: `scripts/install.sh` handles systemd setup - **Service runs as**: Dedicated user (created by installer) - **Offline resilience**: SQLite buffer survives network outages - **Health monitoring**: HTTP endpoint `http://localhost:3030/health` - **Prometheus metrics**: Available at `http://localhost:3030/metrics` ## Integration with Veridian Backend **Webhook/POST endpoint format** (must match Veridian backend expectations): ``` POST /api/v1/sensor-readings Authorization: Bearer {backendApiKey} Content-Type: application/json { "facilityId": "uuid", "readings": [ { "sensorId": "string", "roomId": "uuid", "timestamp": "ISO8601", "temperature": number, "humidity": number } ] } ``` Before changing this format, ALWAYS check the Veridian backend API specification.