# GuruRMM - Complete Reference Documentation

**Project:** GuruRMM - Remote Monitoring and Management Platform
**Version:** Server 0.2.0 / Agent 0.3.5 (deployed as 0.5.1)
**Last Updated:** 2026-02-17

---

## Table of Contents

1. [Project Overview](#project-overview)
2. [Architecture](#architecture)
3. [API Endpoints](#api-endpoints)
4. [WebSocket Protocol](#websocket-protocol)
5. [Command Execution](#command-execution)
6. [Claude Code Integration](#claude-code-integration)
7. [Agent Configuration](#agent-configuration)
8. [Deployed Agents](#deployed-agents)
9. [Database](#database)
10. [Authentication](#authentication)
11. [Auto-Update System](#auto-update-system)
12. [Known Issues](#known-issues)
13. [Development](#development)
14. [File Structure](#file-structure)

---

## Project Overview

GuruRMM is a Remote Monitoring and Management (RMM) platform built entirely in Rust. It provides real-time agent monitoring, remote command execution, system metrics collection, and service watchdog capabilities for managed IT environments.

### Technology Stack

| Component  | Technology                              | Version |
|------------|-----------------------------------------|---------|
| Server     | Rust (Axum 0.7, SQLx 0.8, PostgreSQL)  | 0.2.0   |
| Agent      | Rust (cross-platform, native service)   | 0.3.5 (deployed as 0.5.1) |
| Dashboard  | React + TypeScript + Vite               | --      |
| Real-time  | WebSocket (tokio-tungstenite)           | --      |
| Database   | PostgreSQL                              | --      |

---

## Architecture

### Server

- **Internal Address:** 172.16.3.30:3001
- **Production URL:** https://rmm-api.azcomputerguru.com
- **WebSocket Endpoint:** wss://rmm-api.azcomputerguru.com/ws
- **Database:** PostgreSQL (same server)
- **Service:** systemd unit `gururmm-server`
- **Source:** `D:\ClaudeTools\projects\msp-tools\guru-rmm\server\`

### Agent

- **Windows Service Name:** GuruRMM (uses native-service feature)
- **Legacy Mode:** NSSM wrapper for Windows 7 / Server 2008 R2
- **Config Path:** `C:\ProgramData\GuruRMM\agent.toml`
- **Binary Path:** `C:\Program Files\GuruRMM\gururmm-agent.exe`
- **Source:** `D:\ClaudeTools\projects\msp-tools\guru-rmm\agent\`

### Communication Model

```
+-------------------+       WebSocket (persistent, bidirectional)       +-------------------+
|   GuruRMM Agent   | <-----------------------------------------------> |  GuruRMM Server   |
| (Windows/Linux)   |                                                   |  (Axum + Tokio)   |
+-------------------+                                                   +-------------------+
                                                                               |
                                                                               | REST API (JWT)
                                                                               v
                                                                        +-------------------+
                                                                        |    Dashboard      |
                                                                        |  (React + TS)     |
                                                                        +-------------------+
```

- **Primary:** WebSocket -- persistent bidirectional connection between agent and server
- **Legacy Fallback:** REST heartbeat polling -- [WARNING] NOT FULLY IMPLEMENTED
- **Auth:** API key sent in initial WebSocket authentication message
- **Site-Based Auth:** WORD-WORD-NUMBER format site codes combined with device_id

---

## API Endpoints

### Authentication

| Method | Path               | Description                | Auth Required |
|--------|--------------------|----------------------------|---------------|
| POST   | /api/auth/login    | User login (email/password -> JWT) | No    |
| POST   | /api/auth/register | User registration          | No (disabled) |
| GET    | /api/auth/me       | Get current user info      | Yes           |

### Clients

| Method | Path                    | Description             | Auth Required |
|--------|-------------------------|-------------------------|---------------|
| GET    | /api/clients            | List all clients        | Yes           |
| POST   | /api/clients            | Create client           | Yes           |
| GET    | /api/clients/:id        | Get client by ID        | Yes           |
| PUT    | /api/clients/:id        | Update client           | Yes           |
| DELETE | /api/clients/:id        | Delete client           | Yes           |
| GET    | /api/clients/:id/sites  | List client's sites     | Yes           |

### Sites

| Method | Path                           | Description              | Auth Required |
|--------|--------------------------------|--------------------------|---------------|
| GET    | /api/sites                     | List all sites           | Yes           |
| POST   | /api/sites                     | Create site              | Yes           |
| GET    | /api/sites/:id                 | Get site by ID           | Yes           |
| PUT    | /api/sites/:id                 | Update site              | Yes           |
| DELETE | /api/sites/:id                 | Delete site              | Yes           |
| POST   | /api/sites/:id/regenerate-key  | Regenerate site API key  | Yes           |

### Agents

| Method | Path                     | Description                          | Auth Required |
|--------|--------------------------|--------------------------------------|---------------|
| GET    | /api/agents              | List all agents                      | Yes           |
| POST   | /api/agents              | Register agent (authenticated)       | Yes           |
| GET    | /api/agents/stats        | Agent statistics                     | Yes           |
| GET    | /api/agents/unassigned   | List unassigned agents               | Yes           |
| GET    | /api/agents/:id          | Get agent details                    | Yes           |
| DELETE | /api/agents/:id          | Delete agent                         | Yes           |
| POST   | /api/agents/:id/move     | Move agent to different site         | Yes           |
| GET    | /api/agents/:id/state    | Get agent state (network, metrics)   | Yes           |

### Commands

| Method | Path                       | Description                | Auth Required |
|--------|----------------------------|----------------------------|---------------|
| POST   | /api/agents/:id/command    | Send command to agent      | Yes           |
| GET    | /api/commands              | List recent commands       | Yes           |
| GET    | /api/commands/:id          | Get command status/result  | Yes           |

### Metrics

| Method | Path                       | Description               | Auth Required |
|--------|----------------------------|---------------------------|---------------|
| GET    | /api/agents/:id/metrics    | Get agent metrics history | Yes           |
| GET    | /api/metrics/summary       | Metrics summary           | Yes           |

### Legacy Agent Endpoints

These endpoints do **not** require JWT authentication. They are used by agents in legacy polling mode.

| Method | Path                          | Description                  | Auth Required |
|--------|-------------------------------|------------------------------|---------------|
| POST   | /api/agent/register-legacy    | Register with site code      | No            |
| POST   | /api/agent/heartbeat          | Agent heartbeat              | No            |
| POST   | /api/agent/command-result     | Submit command result        | No            |

[WARNING] Legacy heartbeat returns empty `pending_commands` -- not implemented (agents.rs line 334).
[WARNING] Legacy command-result endpoint does not store results (agents.rs lines 354-360).

### WebSocket

| Method | Path | Description            | Auth Required       |
|--------|------|------------------------|---------------------|
| GET    | /ws  | WebSocket upgrade      | API key in auth msg |

---

## WebSocket Protocol

### Connection Flow

1. Client initiates WebSocket upgrade to `wss://rmm-api.azcomputerguru.com/ws`
2. Agent sends authentication message with API key and device info
3. Server validates API key (SHA256 hash match or site code lookup)
4. On success, server registers the WebSocket connection for the agent
5. Bidirectional message exchange begins

### Message Types

**Agent -> Server:**

- `Auth` -- Initial authentication payload (api_key, hostname, os_info, version)
- `Heartbeat` -- Periodic keepalive
- `MetricsReport` -- System metrics (CPU, memory, disk, network)
- `NetworkState` -- Network configuration snapshot (hash-based change detection)
- `CommandResult` -- Result of executed command (exit_code, stdout, stderr, duration)
- `WatchdogEvent` -- Service monitoring event

**Server -> Agent:**

- `AuthResponse` -- Success/failure of authentication
- `Command` -- Command to execute (CommandPayload)
- `Update` -- Auto-update instruction (download_url, checksum)
- `Ping` -- Keepalive ping

---

## Command Execution

### Command Types

| Type         | Description                                  | Shell Used                                  |
|--------------|----------------------------------------------|---------------------------------------------|
| shell        | System shell command                         | cmd.exe (Windows), /bin/sh (Unix)           |
| powershell   | PowerShell command                           | powershell -NoProfile -NonInteractive -Command |
| python       | Python inline code                           | python -c                                   |
| script       | Custom interpreter                           | Configurable                                |
| claude_task  | Claude Code task execution (special handler) | Claude Code CLI                             |

### Command Flow

```
1. Dashboard sends POST /api/agents/:id/command
   Body: { command_type, command, timeout_seconds, elevated }

2. Server creates command record in database (status = pending)

3. If agent is connected via WebSocket:
   -> Server sends command via WebSocket
   -> Status updated to "running"

4. If agent is offline:
   -> Command stays as "pending" (queued)

5. Agent receives command and executes it

6. Agent sends CommandResult back via WebSocket
   -> { id, exit_code, stdout, stderr, duration_ms }

7. Server updates database with result
```

### Command States

| State     | Description                                    |
|-----------|------------------------------------------------|
| pending   | Created, agent offline or not yet sent         |
| running   | Sent to agent via WebSocket, awaiting result   |
| completed | Agent reported exit_code = 0                   |
| failed    | Agent reported exit_code != 0                  |

### [BUG] Server-Agent Command Type Mismatch

This is a **critical** known bug that prevents all remote command execution.

**Root Cause:**

The server's `CommandPayload` serializes `command_type` as a plain JSON string:

```json
{"command_type": "powershell", "command": "Get-Process", ...}
```

The agent's `CommandPayload` expects `command_type` as a Rust enum (`CommandType::PowerShell`), which serde deserializes from an object or tagged format, not a bare string.

**Result:** Serde deserialization fails silently on the agent side. Commands are never executed. All commands remain in "running" state permanently because no `CommandResult` is ever sent back.

**Fix Required:** Either:
- Change the server to serialize `command_type` in the enum format the agent expects, OR
- Change the agent to accept plain string values for `command_type`

---

## Claude Code Integration

### Architecture

The agent includes a built-in Claude Code executor for running AI-assisted tasks.

- **Singleton:** Global `ClaudeExecutor` via `once_cell::Lazy`
- **Working Directory:** Restricted to `C:\Shares\test\` only
- **Rate Limit:** 10 tasks per hour (sliding window)
- **Max Concurrent:** 2 simultaneous tasks
- **Default Timeout:** 300 seconds (max 600)
- **Input Sanitization:** Blocks `& | ; $ ( ) < > \` \n \r`

### Claude Task Command Format

The server sends:

```json
{
  "type": "command",
  "payload": {
    "id": "uuid",
    "command_type": "claude_task",
    "command": "task description",
    "timeout_seconds": 300,
    "elevated": false
  }
}
```

[WARNING] This also suffers from the command type mismatch bug. The agent expects `command_type` to be an object for ClaudeTask:

```json
{
  "claude_task": {
    "task": "...",
    "working_directory": "...",
    "context_files": [...]
  }
}
```

### Exit Codes

| Code | Meaning                                  |
|------|------------------------------------------|
| 0    | Task completed successfully              |
| 1    | Task failed                              |
| 124  | Task timed out                           |
| -1   | Executor error (rate limit, validation)  |

---

## Agent Configuration

### agent.toml Format

```toml
[server]
url = "wss://rmm-api.azcomputerguru.com/ws"
api_key = "SITE-CODE-1234"  # or grmm_xxxxx API key

[metrics]
interval_seconds = 60  # Range: 10-3600, default: 60
collect_cpu = true
collect_memory = true
collect_disk = true
collect_network = true

[watchdog]
enabled = true
check_interval_seconds = 30

[[watchdog.services]]
name = "ServiceName"
action = "restart"
max_restarts = 3
restart_cooldown_seconds = 60
```

### Hardcoded Intervals

These values are currently not configurable via `agent.toml`:

| Interval                   | Value       | Notes                          |
|----------------------------|-------------|--------------------------------|
| Heartbeat                  | 30 seconds  |                                |
| Network state check        | 30 seconds  | Uses hash-based change detection |
| Connection idle timeout    | 90 seconds  |                                |
| Auth timeout               | 10 seconds  |                                |
| Reconnect delay            | 10 seconds  |                                |
| Command execution timeout  | 300 seconds | Configurable per command       |

---

## Deployed Agents

| Hostname    | Agent ID (prefix) | Version | OS                          | Status  |
|-------------|--------------------|---------|-----------------------------|---------|
| ACG-M-L5090 | 97f63c3b-...      | 0.5.1   | Windows 11 (26200)          | online  |
| AD2         | d28a1c90-...      | 0.5.1   | Windows Server 2016 (14393) | online  |
| gururmm     | 8cd0440f-...      | 0.5.1   | Ubuntu 22.04                | offline |
| SL-SERVER   | 2585f6d5-...      | 0.5.1   | unknown                     | offline |
| SL-SERVER   | dff818e6-...      | 0.5.1   | unknown                     | online  |

---

## Database

### Connection Details

| Parameter | Value                              |
|-----------|------------------------------------|
| Host      | 172.16.3.30                        |
| Port      | 5432                               |
| Database  | gururmm                           |
| User      | gururmm                           |
| Password  | 43617ebf7eb242e814ca9988cc4df5ad   |

### Key Tables

| Table               | Description                                    |
|---------------------|------------------------------------------------|
| users               | User accounts (JWT auth, Argon2id hashing)     |
| clients             | Client organizations                           |
| sites               | Physical locations with API keys               |
| agents              | RMM agent instances                            |
| agent_state         | Latest agent state (network, metrics snapshot) |
| agent_updates       | Agent update tracking                          |
| alerts              | System alerts                                  |
| commands            | Remote command execution log                   |
| metrics             | Performance metrics time series                |
| policies            | Configuration policies                         |
| registration_tokens | Agent registration tokens                      |
| watchdog_events     | Service monitoring events                      |

---

## Authentication

### API Authentication (JWT)

1. Send `POST /api/auth/login` with `{ email, password }`
2. Server validates credentials (Argon2id password hash)
3. Returns JWT token (24-hour expiry)
4. Include token in subsequent requests: `Authorization: Bearer <token>`

**Admin Credentials:**

| Field    | Value                              |
|----------|------------------------------------|
| Email    | claude-api@azcomputerguru.com      |
| Password | ClaudeAPI2026!@#                   |

### Agent Authentication (API Key)

Two authentication modes:

1. **Direct API Key** -- Agent sends `grmm_xxxxx` format key, server matches against `api_key_hash` (SHA256) in agents table
2. **Site-Based** -- Agent sends site code (WORD-WORD-NUMBER format, e.g., `DARK-GROVE-7839`) combined with `device_id`, server looks up site and registers/matches agent

### SSO (Optional)

- **Provider:** Microsoft Entra ID
- **Client ID:** 18a15f5d-7ab8-46f4-8566-d7b5436b84b6

---

## Auto-Update System

### Update Flow

```
1. Agent connects via WebSocket and sends its version in the auth payload

2. Server checks if a newer version is available for the agent's OS/architecture

3. If update needed:
   -> Server sends Update message with download_url and SHA256 checksum

4. Agent downloads the new binary from the download URL

5. Agent verifies the SHA256 checksum

6. Agent replaces its own binary and restarts

7. On reconnection, agent reports previous_version in auth payload

8. Server marks the update as completed
```

### Download Location

- **Server Path:** `/var/www/gururmm/downloads/`
- **Public URL:** `https://rmm-api.azcomputerguru.com/downloads/`

---

## Known Issues

### CRITICAL

| ID | Type       | Description                                                                                |
|----|------------|--------------------------------------------------------------------------------------------|
| 1  | [BUG]      | Command type mismatch between server (String) and agent (Enum) -- commands never execute   |
| 2  | [TODO]     | Legacy heartbeat returns empty pending_commands (agents.rs line 334)                       |
| 3  | [TODO]     | Legacy command-result endpoint does not store results (agents.rs lines 354-360)            |
| 4  | [SECURITY] | CORS configured with AllowOrigin::Any -- should be restricted to known origins             |

### MAJOR

| ID | Description                                                                    |
|----|--------------------------------------------------------------------------------|
| 1  | No command timeout enforcement on server side                                  |
| 2  | No retry logic for failed WebSocket sends                                      |
| 3  | Database inconsistency: agent shows "online" but command sends fail silently   |
| 4  | Missing database indexes on frequently queried columns                         |
| 5  | No rate limiting on command submissions                                        |

### MINOR

| ID | Description                                                              |
|----|--------------------------------------------------------------------------|
| 1  | Hardcoded intervals (heartbeat, network check) not configurable          |
| 2  | Watchdog events logged but not stored in database                        |
| 3  | No log rotation configured                                              |
| 4  | Unicode characters in agent output (should use ASCII per coding guidelines) |

---

## Development

### Building

```bash
# Server
cd server && cargo build --release

# Agent (Windows, native service mode)
cd agent && cargo build --release

# Agent (Legacy mode for Windows 7 / Server 2008 R2)
cd agent && cargo build --release --features legacy --no-default-features
```

### Testing

```bash
cargo test         # Run unit tests
cargo clippy       # Run linter
cargo fmt --check  # Check formatting
```

### Deploying the Server

```bash
# On gururmm server (172.16.3.30)
systemctl stop gururmm-server
cp target/release/gururmm-server /opt/gururmm/
systemctl start gururmm-server
journalctl -u gururmm-server -f
```

### Deploying the Agent

```cmd
REM On target Windows machine
sc stop GuruRMM
copy gururmm-agent.exe "C:\Program Files\GuruRMM\gururmm-agent.exe"
sc start GuruRMM
```

---

## File Structure

```
D:\ClaudeTools\projects\msp-tools\guru-rmm\
|
+-- agent/
|   +-- src/
|   |   +-- main.rs              # Entry point, CLI parsing, service install
|   |   +-- config.rs            # TOML config loading and validation
|   |   +-- claude.rs            # Claude Code executor (rate-limited singleton)
|   |   +-- service.rs           # Windows service handler (native-service feature)
|   |   +-- device_id.rs         # Hardware-based device ID generation
|   |   +-- transport/
|   |   |   +-- mod.rs           # Message types (AgentMessage, ServerMessage, CommandType enum)
|   |   |   +-- websocket.rs     # WebSocket client, reconnection, command execution
|   |   +-- metrics/
|   |   |   +-- mod.rs           # System metrics collection, network state hashing
|   |   +-- updater/
|   |       +-- mod.rs           # Self-update logic (download, verify, replace)
|   +-- deploy/                  # Deployment configs per site
|   +-- Cargo.toml               # v0.3.5, features: native-service, legacy
|
+-- server/
|   +-- src/
|   |   +-- main.rs              # Axum server setup, router, middleware
|   |   +-- api/
|   |   |   +-- mod.rs           # Route definitions and grouping
|   |   |   +-- agents.rs        # Agent management + legacy polling endpoints
|   |   |   +-- commands.rs      # Command dispatch and status tracking
|   |   |   +-- auth.rs          # JWT login, registration, user info
|   |   |   +-- clients.rs       # Client CRUD operations
|   |   |   +-- sites.rs         # Site management and API key regeneration
|   |   |   +-- metrics.rs       # Metrics query endpoints
|   |   +-- ws/
|   |   |   +-- mod.rs           # WebSocket handler, ServerMessage types, CommandPayload (String type)
|   |   +-- db/
|   |   |   +-- agents.rs        # Agent database operations
|   |   |   +-- commands.rs      # Command database operations
|   |   +-- auth/
|   |       +-- mod.rs           # JWT middleware and token validation
|   +-- Cargo.toml               # v0.2.0
|
+-- dashboard/                   # React frontend (if present)
|
+-- docs/
    +-- FEATURE_ROADMAP.md       # Complete feature plan (654 lines)
    +-- REMEDIATION_PLAN.md      # Security and code review (1277 lines)
```

---

## Quick Reference

| Item               | Value                                       |
|--------------------|---------------------------------------------|
| Server URL         | https://rmm-api.azcomputerguru.com          |
| WebSocket URL      | wss://rmm-api.azcomputerguru.com/ws         |
| Internal Address   | 172.16.3.30:3001                            |
| Database           | PostgreSQL @ 172.16.3.30:5432/gururmm       |
| Service Name       | gururmm-server (systemd)                    |
| Agent Service      | GuruRMM (Windows SCM)                       |
| Agent Config       | C:\ProgramData\GuruRMM\agent.toml           |
| Agent Binary       | C:\Program Files\GuruRMM\gururmm-agent.exe  |
| Downloads          | https://rmm-api.azcomputerguru.com/downloads/ |
| Admin Email        | claude-api@azcomputerguru.com               |
| SSO Client ID      | 18a15f5d-7ab8-46f4-8566-d7b5436b84b6       |

---

*Document generated 2026-02-17. Source of truth for GuruRMM project reference.*
