     1→# GuruRMM Feature Roadmap
     2→
     3→This document tracks potential features for consideration. Features are categorized by area and marked with priority/status as planning progresses.
     4→
     5→## Legend
     6→- [ ] Not started
     7→- [~] In consideration
     8→- [x] Implemented
     9→- Priority: P1 (critical), P2 (important), P3 (nice-to-have)
    10→
    11→---
    12→
    13→## Core Agent Features
    14→
    15→### Monitoring & Metrics
    16→- [ ] CPU, RAM, disk usage (basic) - P1
    17→- [ ] Process monitoring (top processes by resource) - P2
    18→- [ ] Service status monitoring - P1
    19→- [ ] Disk health (SMART data) - P2
    20→- [ ] Network interface stats - P2
    21→- [ ] Custom metric collectors (plugin system) - P3
    22→- [ ] Windows Event Log monitoring - P2
    23→- [ ] Linux syslog/journald monitoring - P2
    24→- [ ] Application-specific monitors (SQL Server, IIS, Apache, etc.) - P3
    25→
    26→### Remote Commands
    27→- [ ] Execute shell commands - P1
    28→- [ ] PowerShell support (Windows) - P1
    29→- [ ] Bash support (Linux/Mac) - P1
    30→- [ ] Command templates (reusable scripts) - P2
    31→- [ ] Scheduled commands (cron-like) - P2
    32→- [ ] Command approval workflow - P3
    33→- [ ] Command audit logging - P1
    34→
    35→### File Operations
    36→- [ ] File transfer (push/pull) - P2
    37→- [ ] File browser - P3
    38→- [ ] Configuration file management - P2
    39→- [ ] Backup file retrieval - P3
    40→
    41→### Software Management
    42→- [ ] Installed software inventory - P2
    43→- [ ] Software deployment (silent install) - P2
    44→- [ ] Patch management integration - P3
    45→- [ ] Windows Update status - P2
    46→- [ ] Package manager integration (apt, yum, chocolatey, winget) - P3
    47→
    48→### Agent Updates
    49→- [ ] Built-in update handler (not shell script based) - P1
    50→- [ ] Server sends update command with version, URL, checksum - P1
    51→- [ ] Download to temp, verify SHA256, replace binary - P1
    52→- [ ] Platform-specific restart logic - P1
    53→- [ ] Backup previous binary for rollback - P2
    54→- [ ] Auto-rollback if new version fails to connect - P2
    55→- [ ] Version tracking in server database - P1
    56→- [ ] Fleet-wide version dashboard - P2
    57→- [ ] Staged rollouts (% of agents at a time) - P3
    58→- [ ] Update scheduling (maintenance windows) - P2
    59→
    60→### White-Labeling / Branding
    61→MSPs need to brand the agent with their company identity.
    62→
    63→#### Install-Time Branding
    64→- [ ] Custom service name (`--service-name "AcmeTech Agent"`) - P2
    65→- [ ] Custom display name (`--display-name "AcmeTech Monitor"`) - P2
    66→- [ ] Custom install path (`--install-path "C:\Program Files\AcmeTech"`) - P2
    67→- [ ] Custom binary name (rename on install) - P3
    68→- [ ] Branding config file (alternative to CLI flags) - P2
    69→
    70→#### Runtime Branding (Server-Managed)
    71→- [ ] Branding config pushed from server - P2
    72→- [ ] MSP logo/icon URL - P2
    73→- [ ] Support contact info (phone, email, URL) - P2
    74→- [ ] Custom "About" dialog content - P2
    75→- [ ] Per-customer branding overrides - P3
    76→
    77→### System Tray / End-User Self-Service (Windows/macOS)
    78→Interactive tray icon for end users to access self-service features.
    79→
    80→#### Tray Infrastructure
    81→- [ ] System tray icon (Windows) - P2
    82→- [ ] Menu bar icon (macOS) - P2
    83→- [ ] Custom icon support (MSP branding) - P2
    84→- [ ] Connection status indicator (connected/disconnected) - P2
    85→- [ ] Tooltip with basic info (hostname, status) - P2
    86→
    87→#### Built-In Actions
    88→- [ ] Show System Info dialog (hostname, IP, OS, agent version) - P2
    89→- [ ] Create Support Ticket (opens form or portal link) - P2
    90→- [ ] Screenshot to Ticket (capture screen, attach to new ticket) - P2
    91→- [ ] About dialog (version, MSP branding, support contact) - P2
    92→
    93→#### Admin-Definable Custom Actions
    94→Server pushes custom tray menu items that execute predefined commands.
    95→- [ ] Custom action data model (label, icon, command, elevation, confirm) - P2
    96→- [ ] Action types: RunCommand, RestartService, OpenUrl, RunScript - P2
    97→- [ ] Confirmation dialogs ("Are you sure?") - P2
    98→- [ ] Elevation support (run as admin) - P2
    99→- [ ] Per-customer action sets - P2
   100→- [ ] Action categories/submenus - P3
   101→- [ ] Success/failure notifications - P2
   102→
   103→#### Example Custom Actions
   104→```
   105→├── Quick Actions
   106→│   ├── Restart Print Spooler
   107→│   ├── Clear Temp Files
   108→│   ├── Restart Network Adapter
   109→│   ├── Flush DNS Cache
   110→│   └── (admin-defined...)
   111→```
   112→
   113→#### Security
   114→- [ ] Actions are server-defined only (users can't add) - P1
   115→- [ ] Audit logging of tray action executions - P2
   116→- [ ] Optional PIN/password for sensitive actions - P3
   117→
   118→---
   119→
   120→## Server/API Features
   121→
   122→### Authentication & Authorization
   123→- [ ] JWT authentication - P1
   124→- [ ] API keys for agents - P1
   125→- [ ] Role-based access control (RBAC) - P2
   126→- [ ] Multi-tenant support - P3
   127→- [ ] SSO integration (SAML, OAuth) - P3
   128→- [ ] 2FA/MFA support - P2
   129→
   130→### Agent Management
   131→- [ ] Agent registration/enrollment - P1
   132→- [ ] Agent grouping/tagging - P2
   133→- [ ] Agent policies (config profiles) - P2
   134→- [ ] Bulk operations - P2
   135→- [ ] Agent health monitoring - P1
   136→- [ ] Auto-update agents - P2
   137→
   138→### Site Proxy / Local Node
   139→- [ ] Agent can operate as site proxy/hub - P2
   140→- [ ] Local agents connect to proxy instead of cloud - P2
   141→- [ ] Proxy aggregates metrics and forwards to server - P2
   142→- [ ] Store-and-forward when WAN is unavailable - P2
   143→- [ ] Local command relay (proxy executes commands on local agents) - P2
   144→- [ ] Reduced WAN bandwidth (batched/compressed uploads) - P3
   145→- [ ] Failover between multiple proxies at site - P3
   146→- [ ] Proxy discovery (agents auto-find local proxy) - P3
   147→- [ ] Mesh communication between proxies - P3
   148→- [ ] Local caching of scripts/files for faster deployment - P2
   149→- [ ] Site-level alerting (proxy can alert locally if WAN down) - P3
   150→
   151→### Alerting
   152→- [ ] Threshold-based alerts - P1
   153→- [ ] Alert escalation - P2
   154→- [ ] Alert suppression/maintenance windows - P2
   155→- [ ] Email notifications - P1
   156→- [ ] SMS notifications - P3
   157→- [ ] Webhook notifications - P2
   158→- [ ] PagerDuty/Opsgenie integration - P3
   159→- [ ] Slack/Teams integration - P2
   160→
   161→### Reporting & Analytics
   162→- [ ] Unified reporting engine (works across RMM, PSA, all modules) - P1
   163→- [ ] Clean, modern report templates - P1
   164→- [ ] Custom report builder (drag-and-drop) - P2
   165→- [ ] Scheduled report delivery (email, portal) - P2
   166→- [ ] White-label/branding support - P2
   167→- [ ] Export formats: PDF, Excel, CSV, HTML - P1
   168→- [ ] Executive summary dashboards - P2
   169→- [ ] Uptime/SLA reports - P2
   170→- [ ] Resource usage trends with visualizations - P2
   171→- [ ] Ticket metrics (response time, resolution time, volume) - P2
   172→- [ ] Technician performance/utilization - P2
   173→- [ ] Customer health scores - P3
   174→- [ ] Revenue/profitability by customer - P3
   175→- [ ] Report templates library (pre-built, shareable) - P2
   176→
   177→#### Data Granularity & Flexible Calculations
   178→The data model must support arbitrary business logic, not just canned reports.
   179→
   180→- [ ] Granular time entry data (tech, client, ticket, service type, rate plan) - P1
   181→- [ ] Effective rate tracking per client/plan (block rate vs hourly vs plan) - P2
   182→- [ ] Calculated fields / custom formulas in reports - P2
   183→- [ ] Multi-variable calculations (hours × effective rate × commission %) - P2
   184→- [ ] Aggregation at any level (tech, client, service type, date range) - P2
   185→- [ ] Rate plan / contract type as first-class data dimension - P2
   186→- [ ] Historical rate tracking (rate was X on this date) - P2
   187→- [ ] Payroll-ready exports (base + commission breakdown) - P2
   188→- [ ] Custom metrics definition (define your own KPIs) - P2
   189→- [ ] Formula builder for complex business rules - P3
   190→- [ ] Drill-down from summary to line-item detail - P2
   191→- [ ] Data warehouse / OLAP cube for complex analytics - P3
   192→- [ ] API access to raw data for external BI tools - P2
   193→
   194→---
   195→
   196→## Dashboard Features
   197→
   198→### Views
   199→- [ ] Agent list with status - P1
   200→- [ ] Agent detail view - P1
   201→- [ ] Real-time metrics charts - P2
   202→- [ ] Map view (geographic) - P3
   203→- [ ] Network topology view - P3
   204→- [ ] Custom dashboards - P3
   205→
   206→### Remote Access
   207→- [ ] Remote terminal (web-based) - P2
   208→- [ ] Remote desktop (RDP/VNC proxy) - P3
   209→- [ ] File manager UI - P3
   210→
   211→### Direct Agent Connection (Admin Tunnel)
   212→- [ ] On-demand reverse tunnel to agent - P2
   213→- [ ] Live interactive shell session (not queued commands) - P2
   214→- [ ] Direct command pipe (real-time stdin/stdout/stderr) - P2
   215→- [ ] Point-to-point encrypted tunnel (WireGuard/custom) - P3
   216→- [ ] Tunnel enables direct SSH/RDP through agent - P3
   217→- [ ] Credential/role-based access (only authorized admins) - P1
   218→- [ ] Agent classification determines tunnel capability - P2
   219→- [ ] Session recording for audit - P2
   220→- [ ] Idle timeout and forced disconnect - P2
   221→- [ ] Concurrent session limits - P3
   222→- [ ] Tunnel through site proxy (when agent behind NAT) - P3
   223→- [ ] Local port forwarding through tunnel - P3
   224→
   225→### User Experience & Interface Design
   226→
   227→#### Design Philosophy
   228→- Beautiful AND functional - no compromise, no "ugly but it works"
   229→- Clean, modern aesthetic with purposeful whitespace
   230→- Information density without clutter
   231→- Consistent design language across all modules
   232→- Accessibility (WCAG compliance, screen readers, keyboard nav)
   233→
   234→#### Customization
   235→- [ ] Dark/light/system theme - P2
   236→- [ ] Customizable dashboard layouts (drag-and-drop widgets) - P2
   237→- [ ] User-defined color accents/branding - P2
   238→- [ ] Configurable data density (compact/comfortable/spacious) - P2
   239→- [ ] Saved views and workspace layouts - P2
   240→- [ ] Per-user preferences synced across devices - P2
   241→- [ ] Custom CSS injection for white-label deployments - P3
   242→
   243→#### Real-Time Updates
   244→- [ ] WebSocket-based live data (no page refresh) - P1
   245→- [ ] Real-time agent status changes - P1
   246→- [ ] Live metric updates on dashboards - P1
   247→- [ ] Instant alert notifications (toast/badge) - P1
   248→- [ ] Collaborative indicators (who else is viewing this ticket) - P3
   249→- [ ] Optimistic UI updates (instant feedback, sync in background) - P2
   250→
   251→#### Third-Party Module Integration
   252→- [ ] Plugin/module API for UI extensions - P2
   253→- [ ] Dashboard widget SDK (third parties can add widgets) - P2
   254→- [ ] Panel embedding (iframe or native component) - P2
   255→- [ ] Unified navigation (third-party modules appear native) - P2
   256→- [ ] Shared authentication context - P2
   257→- [ ] Event bus for cross-module communication - P2
   258→- [ ] Style guide/component library for consistent third-party UI - P2
   259→
   260→#### Core UX
   261→- [ ] Mobile responsive (PWA capable) - P2
   262→- [ ] Keyboard shortcuts with command palette (Cmd+K) - P2
   263→- [ ] Saved searches/filters - P2
   264→- [ ] Bulk selection and actions - P2
   265→- [ ] Contextual right-click menus - P3
   266→- [ ] Undo/redo for destructive actions - P2
   267→- [ ] Breadcrumb navigation - P1
   268→- [ ] Global search (agents, tickets, customers, docs) - P1
   269→
   270→### Customer Portal (End-User Facing)
   271→- [ ] Branded portal per customer (white-label) - P2
   272→- [ ] Ticket submission and tracking - P1
   273→- [ ] View open/closed ticket history - P1
   274→- [ ] Asset inventory view (their devices) - P2
   275→- [ ] Service status dashboard (are things healthy?) - P2
   276→- [ ] Meaningful metrics (uptime, response times, SLA status) - P2
   277→- [ ] Invoice/billing history - P3
   278→- [ ] Knowledge base / self-service articles - P2
   279→- [ ] Scheduled maintenance notifications - P2
   280→- [ ] Contact directory (who to call for what) - P2
   281→- [ ] Document library (contracts, policies, procedures) - P3
   282→- [ ] Approval workflows (quote approvals, change requests) - P3
   283→- [ ] Mobile-friendly / PWA - P2
   284→
   285→---
   286→
   287→## Integration Features
   288→
   289→### PSA/Ticketing Integration (External)
   290→- [ ] ConnectWise Manage - P3
   291→- [ ] Autotask - P3
   292→- [ ] HaloPSA - P3
   293→- [ ] Generic webhook for tickets - P2
   294→- [ ] Pluggable PSA adapter architecture - P2
   295→
   296→### GuruPSA (Companion CRM/PSA) - Separate Project
   297→- [ ] Core ticketing system - P1
   298→- [ ] Customer/company management - P1
   299→- [ ] Contact management - P1
   300→- [ ] Asset linking (from RMM) - P1
   301→- [ ] Time tracking - P2
   302→- [ ] Contracts/SLA management - P2
   303→- [ ] Quoting/proposals - P3
   304→- [ ] Project management - P3
   305→- [ ] Knowledge base - P2
   306→- [ ] Technician mobile app - P3
   307→- [ ] Calendar/scheduling - P3
   308→- [ ] Email integration (ticket from email) - P1
   309→- [ ] Alert-to-ticket automation - P1
   310→- [ ] Shared reporting engine with RMM - P1
   311→
   312→### Automated Usage-Based Billing (GuruPSA + RMM Integration)
   313→No more manual agent counting. Usage data flows automatically to invoices.
   314→
   315→#### Core Billing Engine
   316→- [ ] Recurring invoice generation - P2
   317→- [ ] Usage metering framework (count anything, bill for it) - P2
   318→- [ ] Billing rules engine (per-agent, per-user, tiered, flat) - P2
   319→- [ ] Proration for mid-cycle changes - P2
   320→- [ ] Invoice approval workflow (review before send) - P2
   321→- [ ] Multi-currency support - P3
   322→- [ ] Tax calculation / integration - P3
   323→- [ ] Payment gateway integration (Stripe, QuickBooks, etc.) - P2
   324→
   325→#### RMM-to-Invoice Automation
   326→- [ ] Live agent count per customer - P1
   327→- [ ] Auto-sync agent count to invoice line items - P2
   328→- [ ] Agent add/remove reflected immediately in billing - P2
   329→- [ ] Billable vs non-billable agent classification - P2
   330→- [ ] Per-agent-type pricing (server vs workstation) - P2
   331→- [ ] Audit trail (agent added on X date, removed on Y) - P2
   332→- [ ] Usage snapshots for billing period - P2
   333→- [ ] Dispute resolution (customer says "I only had 10") - P2
   334→
   335→#### Third-Party Usage Integration
   336→- [ ] Generic API adapter for usage data - P2
   337→- [ ] MSP Backup integration (licenses, storage used) - P2
   338→- [ ] Microsoft 365 license count (via Graph API) - P2
   339→- [ ] Google Workspace license count - P3
   340→- [ ] DNS/domain registrar counts - P3
   341→- [ ] Security product license counts - P3
   342→- [ ] Storage/bandwidth metering - P3
   343→- [ ] Custom API connector builder - P3
   344→
   345→#### Billing Intelligence
   346→- [ ] Usage trending (predict next invoice) - P3
   347→- [ ] Anomaly alerts (sudden agent spike/drop) - P2
   348→- [ ] Margin analysis per customer - P3
   349→- [ ] Contract vs actual usage comparison - P2
   350→- [ ] Unbilled usage warnings - P2
   351→
   352→### Unified API Architecture
   353→- [ ] RESTful API for all RMM functions - P1
   354→- [ ] RESTful API for all PSA functions - P1
   355→- [ ] OpenAPI/Swagger documentation - P1
   356→- [ ] Webhook system (outbound events) - P2
   357→- [ ] API versioning strategy - P1
   358→- [ ] Rate limiting and quotas - P2
   359→- [ ] API key management - P1
   360→- [ ] OAuth2 for third-party integrations - P2
   361→- [ ] GraphQL endpoint (optional) - P3
   362→- [ ] Event-driven architecture (pub/sub) - P2
   363→- [ ] Integration SDK/client libraries - P3
   364→
   365→### Documentation
   366→- [ ] IT Glue integration - P3
   367→- [ ] Hudu integration - P3
   368→- [ ] Auto-document discovered info - P3
   369→
   370→### Backup
   371→- [ ] Veeam status monitoring - P3
   372→- [ ] Datto status monitoring - P3
   373→- [ ] Generic backup job monitoring - P2
   374→
   375→### Network
   376→- [ ] SNMP monitoring - P3
   377→- [ ] Network device discovery - P3
   378→- [ ] Bandwidth monitoring - P3
   379→
   380→---
   381→
   382→## Security Features
   383→
   384→### Endpoint Security
   385→- [ ] Antivirus status monitoring - P2
   386→- [ ] Windows Defender management - P2
   387→- [ ] Firewall status - P2
   388→- [ ] Security baseline compliance - P3
   389→- [ ] Vulnerability scanning integration - P3
   390→
   391→### Audit & Compliance
   392→- [ ] Full audit trail - P1
   393→- [ ] Session recording - P3
   394→- [ ] Compliance reporting (SOC2, etc.) - P3
   395→- [ ] Data retention policies - P2
   396→
   397→### Agent Security Hardening (P1 post-alpha)
   398→- [ ] Dependency vulnerability scanning (CI/CD pipeline) - P1
   399→- [ ] Automated CVE monitoring for all dependencies - P1
   400→- [ ] Regular security audits of agent codebase - P1
   401→- [ ] Minimal attack surface (no unnecessary open ports) - P1
   402→- [ ] Code signing for agent binaries - P1
   403→- [ ] Secure update mechanism (signed updates only) - P1
   404→- [ ] Memory-safe language benefits (Rust) - P1
   405→- [ ] Principle of least privilege (drop privs where possible) - P1
   406→- [ ] Certificate pinning for server communication - P2
   407→- [ ] Tamper detection (agent integrity monitoring) - P2
   408→- [ ] Sandboxed command execution option - P3
   409→- [ ] Security disclosure program / responsible disclosure policy - P2
   410→- [ ] Penetration testing (periodic) - P2
   411→- [ ] SBOM (Software Bill of Materials) for transparency - P2
   412→- [ ] Rapid patch deployment capability - P1
   413→
   414→---
   415→
   416→## Infrastructure
   417→
   418→### Deployment
   419→
   420→#### Development/Small Scale
   421→- [ ] Docker Compose deployment - P1
   422→- [ ] Single-server setup (dev, small MSP <500 agents) - P1
   423→
   424→#### Production/Cloud Scale
   425→- [ ] Kubernetes deployment - P2
   426→- [ ] Cloud-native architecture (AWS, Azure, GCP) - P2
   427→- [ ] Horizontal scaling (stateless API servers) - P2
   428→- [ ] Auto-scaling based on load - P2
   429→- [ ] High availability (multi-zone, failover) - P2
   430→- [ ] Load balancing (API, WebSocket, dashboard) - P2
   431→- [ ] Geographic distribution (multi-region) - P3
   432→- [ ] CDN for dashboard/static assets - P2
   433→- [ ] Managed database services (RDS, Cloud SQL) - P2
   434→- [ ] Message queue for agent check-ins (Redis, RabbitMQ, SQS) - P2
   435→- [ ] Connection pooling for 50k+ concurrent agents - P2
   436→- [ ] Read replicas for reporting/analytics queries - P2
   437→- [ ] Tenant isolation (multi-tenant SaaS) - P3
   438→
   439→### Code Signing & Distribution (Pre-Release)
   440→- [ ] Windows EV Code Signing Certificate - P1 (pre-release)
   441→  - Required for SmartScreen reputation
   442→  - ~$400-600/year (DigiCert, Sectigo, GlobalSign)
   443→  - Hardware token required for private key
   444→- [ ] Apple Developer Program enrollment - P1 (pre-release)
   445→  - $99/year - covers macOS signing and notarization
   446→  - Required for Gatekeeper approval on macOS 10.15+
   447→- [ ] Signing pipeline integration (CI/CD) - P1 (pre-release)
   448→- [ ] Notarization workflow for macOS builds - P1 (pre-release)
   449→- [ ] Secure key storage (HSM or hardware token) - P1 (pre-release)
   450→
   451→### Data
   452→- [ ] PostgreSQL backend - P1
   453→- [ ] Redis caching - P2
   454→- [ ] Time-series DB for metrics (InfluxDB/TimescaleDB) - P2
   455→- [ ] Data archival/retention - P2
   456→- [ ] Backup/restore - P1
   457→
   458→---
   459→
   460→## Platform Support
   461→
   462→### Agent Platforms
   463→- [ ] Windows (x64) - P1
   464→- [ ] Windows (ARM64) - P3
   465→- [ ] Linux (x64) - P1
   466→- [ ] Linux (ARM64) - P2
   467→- [ ] macOS (Intel) - P2
   468→- [ ] macOS (Apple Silicon) - P2
   469→- [ ] FreeBSD - P3
   470→
   471→### Mobile Device Management (MDM)
   472→- [ ] iOS/iPadOS agent (MDM profile-based) - P2
   473→- [ ] Android agent (Work Profile / Device Admin) - P2
   474→- [ ] Mobile device inventory - P2
   475→- [ ] App deployment/management - P3
   476→- [ ] Remote lock/wipe - P2
   477→- [ ] Location tracking (with consent) - P3
   478→- [ ] Compliance policies (PIN, encryption) - P2
   479→- [ ] BYOD vs corporate device handling - P3
   480→- [ ] Apple Business Manager integration - P3
   481→- [ ] Android Enterprise integration - P3
   482→- [ ] Mobile management dashboard - P2
   483→- [ ] Push notification for alerts - P2
   484→
   485→### Appliance/NAS Agents
   486→- [ ] Unraid plugin - P2
   487→- [ ] Synology package (DSM) - P2
   488→- [ ] QNAP package (QTS) - P3
   489→- [ ] TrueNAS plugin - P3
   490→- [ ] Netgear ReadyNAS (limited/polling) - P3
   491→- [ ] Docker container agent (for containerized appliances) - P2
   492→- [ ] SNMP-based monitoring (for appliances without agent support) - P2
   493→- [ ] Proxmox integration - P2
   494→- [ ] ESXi/vSphere monitoring - P3
   495→
   496→### Appliance-Specific Metrics
   497→- [ ] RAID/array health status - P2
   498→- [ ] Drive temperatures and SMART data - P2
   499→- [ ] Share/volume utilization - P2
   500→- [ ] Replication/sync job status - P3
   501→- [ ] UPS status (NUT integration) - P2
   502→- [ ] Docker container status (for Unraid/NAS) - P2
   503→- [ ] VM status (Proxmox/ESXi) - P3
   504→- [ ] Backup job status - P2
   505→
   506→### Installation Methods
   507→- [ ] MSI installer (Windows) - P1
   508→- [ ] DEB package (Debian/Ubuntu) - P2
   509→- [ ] RPM package (RHEL/Fedora) - P2
   510→- [ ] Homebrew (macOS) - P3
   511→- [ ] One-liner install script - P1
   512→
   513→---
   514→
   515→## Future Considerations
   516→
   517→### AI/Automation
   518→
   519→#### Ticket Intelligence (P2)
   520→- [ ] Grammar/spelling correction for technician notes
   521→- [ ] Professional tone enhancement (convert shorthand to proper language)
   522→- [ ] Auto-summarization of long ticket threads
   523→- [ ] Smart ticket categorization/tagging based on content
   524→- [ ] Duplicate/related ticket detection (3 people report same issue → merge offer)
   525→
   526→#### Troubleshooting Assistant (P2)
   527→- [ ] Suggest solutions based on similar past tickets
   528→- [ ] Pattern matching on ticket subject/description
   529→- [ ] Alert-to-resolution correlation (what fixed this alert before?)
   530→- [ ] Knowledge base article suggestions
   531→- [ ] "This issue was resolved X times before by doing Y"
   532→
   533→#### Proactive Intelligence (P3)
   534→- [ ] Anomaly detection (ML-based)
   535→- [ ] Auto-remediation scripts (with approval workflow)
   536→- [ ] Natural language queries ("show me servers with high CPU this week")
   537→- [ ] Predictive alerting (disk will be full in 3 days based on trend)
   538→
   539→### Advanced Features
   540→- [ ] Asset lifecycle management - P3
   541→- [ ] License management - P3
   542→- [ ] Cost tracking/billing - P3
   543→- [ ] API for third-party integrations - P2
   544→
   545→(White-labeling moved to Core Agent Features → White-Labeling / Branding)
   546→
   547→---
   548→
   549→## Development Phases
   550→
   551→### Phase 1: Foundation (MVP)
   552→Core RMM functionality - enough to monitor your own clients.
   553→- Agent: heartbeat, basic metrics (CPU, RAM, disk), Windows + Linux
   554→- Server: agent registration, API, database
   555→- Dashboard: agent list, status, basic metrics view
   556→- Alerts: threshold-based, email notification
   557→
   558→### Phase 2: Operational
   559→Day-to-day MSP operations.
   560→- Remote commands, PowerShell/Bash execution
   561→- Patch status, software inventory
   562→- Alert escalation, maintenance windows
   563→- Basic reporting
   564→
   565→### Phase 3: PSA Integration
   566→GuruPSA companion or third-party PSA.
   567→- Ticketing, customer management
   568→- Alert-to-ticket automation
   569→- Time tracking, basic billing
   570→- Customer portal
   571→
   572→### Phase 4: Scale & Polish
   573→Production-ready for broader use.
   574→- Cloud deployment, horizontal scaling
   575→- Advanced reporting, usage-based billing
   576→- UI polish, customization
   577→- Third-party integrations, plugin SDK
   578→
   579→### Phase 5: Intelligence
   580→Differentiation features.
   581→- AI ticket enhancement, troubleshooting suggestions
   582→- Anomaly detection, predictive alerting
   583→- Advanced analytics
   584→
   585→---
   586→
   587→## Design Principles
   588→
   589→### True Integration, Not API Checkboxes
   590→Unlike vendors who claim "API integration" but deliver siloed products that barely talk to each other, GuruRMM and GuruPSA must be designed as a unified system:
   591→
   592→- **Single Action, Full Workflow**: When an admin initiates an EDR scan from the RMM, the PSA should automatically:
   593→  - Create/update a ticket with scan status
   594→  - Log the action against the asset
   595→  - Update documentation with findings
   596→  - Trigger alerts/escalations based on results
   597→  - No manual steps, no copy-paste, no "check the other product"
   598→
   599→- **Bidirectional Context**: A technician viewing a ticket should see:
   600→  - Real-time agent status
   601→  - Recent alerts and metrics
   602→  - One-click remote access
   603→  - Full asset history
   604→  - Not just a link to "go look it up in the RMM"
   605→
   606→- **Event-Driven Architecture**: Actions in one product automatically trigger appropriate responses in others. Not "you can build it yourself with the API" - it works out of the box.
   607→
   608→- **Shared Data Model**: Assets, customers, contacts, and history exist once and are referenced everywhere. No sync conflicts, no duplicate data entry.
   609→
   610→### Avoid the Datto Anti-Pattern
   611→Datto owns ITGlue, Autotask, DattoRMM, and EDR - yet they operate as separate products that happen to have APIs. Example failures to avoid:
   612→- EDR scan results don't auto-create tickets
   613→- RMM alerts require manual ticket creation
   614→- Documentation requires separate manual updates
   615→- "Integration" means "we have an API, build it yourself"
   616→
   617→GuruRMM/GuruPSA should feel like one product with different views, not two products bolted together.
   618→
   619→---
   620→
   621→## Notes
   622→
   623→Add feature ideas and notes here as they come up:
   624→
   625→- GuruPSA will be a separate repo but designed to integrate seamlessly with GuruRMM
   626→- API-first design: both products should be fully controllable via API
   627→- Users can use GuruRMM standalone, GuruPSA standalone, or both together
   628→- Third-party PSA users get first-class integration via pluggable adapters
   629→- Consider shared authentication/SSO between RMM and PSA
   630→
   631→## Project Structure
   632→
   633→```
   634→GuruRMM (this repo)
   635→├── agent/        - Rust agent for endpoints
   636→├── server/       - Rust API server
   637→├── dashboard/    - React web dashboard
   638→└── docs/         - Documentation
   639→
   640→GuruPSA (future repo)
   641→├── server/       - API server (Rust or Node?)
   642→├── dashboard/    - React web dashboard
   643→├── portal/       - Customer portal
   644→└── docs/         - Documentation
   645→
   646→Shared
   647→├── guru-api-sdk/ - Client libraries for API
   648→└── guru-common/  - Shared types/utilities
   649→```
   650→
   651→---
   652→
   653→*Last updated: 2025-12-15*
   654→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

# GuruRMM Feature Roadmap

This document tracks potential features for consideration. Features are categorized by area and marked with priority/status as planning progresses.

## Legend
- [ ] Not started
- [~] In consideration
- [x] Implemented
- Priority: P1 (critical), P2 (important), P3 (nice-to-have)

---

## Core Agent Features

### Monitoring & Metrics
- [ ] CPU, RAM, disk usage (basic) - P1
- [ ] Process monitoring (top processes by resource) - P2
- [ ] Service status monitoring - P1
- [ ] Disk health (SMART data) - P2
- [ ] Network interface stats - P2
- [ ] Custom metric collectors (plugin system) - P3
- [ ] Windows Event Log monitoring - P2
- [ ] Linux syslog/journald monitoring - P2
- [ ] Application-specific monitors (SQL Server, IIS, Apache, etc.) - P3

### Remote Commands
- [ ] Execute shell commands - P1
- [ ] PowerShell support (Windows) - P1
- [ ] Bash support (Linux/Mac) - P1
- [ ] Command templates (reusable scripts) - P2
- [ ] Scheduled commands (cron-like) - P2
- [ ] Command approval workflow - P3
- [ ] Command audit logging - P1

### File Operations
- [ ] File transfer (push/pull) - P2
- [ ] File browser - P3
- [ ] Configuration file management - P2
- [ ] Backup file retrieval - P3

### Software Management
- [ ] Installed software inventory - P2
- [ ] Software deployment (silent install) - P2
- [ ] Patch management integration - P3
- [ ] Windows Update status - P2
- [ ] Package manager integration (apt, yum, chocolatey, winget) - P3

### Agent Updates
- [ ] Built-in update handler (not shell script based) - P1
- [ ] Server sends update command with version, URL, checksum - P1
- [ ] Download to temp, verify SHA256, replace binary - P1
- [ ] Platform-specific restart logic - P1
- [ ] Backup previous binary for rollback - P2
- [ ] Auto-rollback if new version fails to connect - P2
- [ ] Version tracking in server database - P1
- [ ] Fleet-wide version dashboard - P2
- [ ] Staged rollouts (% of agents at a time) - P3
- [ ] Update scheduling (maintenance windows) - P2

### White-Labeling / Branding
MSPs need to brand the agent with their company identity.

#### Install-Time Branding
- [ ] Custom service name (`--service-name "AcmeTech Agent"`) - P2
- [ ] Custom display name (`--display-name "AcmeTech Monitor"`) - P2
- [ ] Custom install path (`--install-path "C:\Program Files\AcmeTech"`) - P2
- [ ] Custom binary name (rename on install) - P3
- [ ] Branding config file (alternative to CLI flags) - P2

#### Runtime Branding (Server-Managed)
- [ ] Branding config pushed from server - P2
- [ ] MSP logo/icon URL - P2
- [ ] Support contact info (phone, email, URL) - P2
- [ ] Custom "About" dialog content - P2
- [ ] Per-customer branding overrides - P3

### System Tray / End-User Self-Service (Windows/macOS)
Interactive tray icon for end users to access self-service features.

#### Tray Infrastructure
- [ ] System tray icon (Windows) - P2
- [ ] Menu bar icon (macOS) - P2
- [ ] Custom icon support (MSP branding) - P2
- [ ] Connection status indicator (connected/disconnected) - P2
- [ ] Tooltip with basic info (hostname, status) - P2

#### Built-In Actions
- [ ] Show System Info dialog (hostname, IP, OS, agent version) - P2
- [ ] Create Support Ticket (opens form or portal link) - P2
- [ ] Screenshot to Ticket (capture screen, attach to new ticket) - P2
- [ ] About dialog (version, MSP branding, support contact) - P2

#### Admin-Definable Custom Actions
Server pushes custom tray menu items that execute predefined commands.
- [ ] Custom action data model (label, icon, command, elevation, confirm) - P2
- [ ] Action types: RunCommand, RestartService, OpenUrl, RunScript - P2
- [ ] Confirmation dialogs ("Are you sure?") - P2
- [ ] Elevation support (run as admin) - P2
- [ ] Per-customer action sets - P2
- [ ] Action categories/submenus - P3
- [ ] Success/failure notifications - P2

#### Example Custom Actions
```
├── Quick Actions
│   ├── Restart Print Spooler
│   ├── Clear Temp Files
│   ├── Restart Network Adapter
│   ├── Flush DNS Cache
│   └── (admin-defined...)
```

#### Security
- [ ] Actions are server-defined only (users can't add) - P1
- [ ] Audit logging of tray action executions - P2
- [ ] Optional PIN/password for sensitive actions - P3

---

## Server/API Features

### Authentication & Authorization
- [ ] JWT authentication - P1
- [ ] API keys for agents - P1
- [ ] Role-based access control (RBAC) - P2
- [ ] Multi-tenant support - P3
- [ ] SSO integration (SAML, OAuth) - P3
- [ ] 2FA/MFA support - P2

### Agent Management
- [ ] Agent registration/enrollment - P1
- [ ] Agent grouping/tagging - P2
- [ ] Agent policies (config profiles) - P2
- [ ] Bulk operations - P2
- [ ] Agent health monitoring - P1
- [ ] Auto-update agents - P2

### Site Proxy / Local Node
- [ ] Agent can operate as site proxy/hub - P2
- [ ] Local agents connect to proxy instead of cloud - P2
- [ ] Proxy aggregates metrics and forwards to server - P2
- [ ] Store-and-forward when WAN is unavailable - P2
- [ ] Local command relay (proxy executes commands on local agents) - P2
- [ ] Reduced WAN bandwidth (batched/compressed uploads) - P3
- [ ] Failover between multiple proxies at site - P3
- [ ] Proxy discovery (agents auto-find local proxy) - P3
- [ ] Mesh communication between proxies - P3
- [ ] Local caching of scripts/files for faster deployment - P2
- [ ] Site-level alerting (proxy can alert locally if WAN down) - P3

### Alerting
- [ ] Threshold-based alerts - P1
- [ ] Alert escalation - P2
- [ ] Alert suppression/maintenance windows - P2
- [ ] Email notifications - P1
- [ ] SMS notifications - P3
- [ ] Webhook notifications - P2
- [ ] PagerDuty/Opsgenie integration - P3
- [ ] Slack/Teams integration - P2

### Reporting & Analytics
- [ ] Unified reporting engine (works across RMM, PSA, all modules) - P1
- [ ] Clean, modern report templates - P1
- [ ] Custom report builder (drag-and-drop) - P2
- [ ] Scheduled report delivery (email, portal) - P2
- [ ] White-label/branding support - P2
- [ ] Export formats: PDF, Excel, CSV, HTML - P1
- [ ] Executive summary dashboards - P2
- [ ] Uptime/SLA reports - P2
- [ ] Resource usage trends with visualizations - P2
- [ ] Ticket metrics (response time, resolution time, volume) - P2
- [ ] Technician performance/utilization - P2
- [ ] Customer health scores - P3
- [ ] Revenue/profitability by customer - P3
- [ ] Report templates library (pre-built, shareable) - P2

#### Data Granularity & Flexible Calculations
The data model must support arbitrary business logic, not just canned reports.

- [ ] Granular time entry data (tech, client, ticket, service type, rate plan) - P1
- [ ] Effective rate tracking per client/plan (block rate vs hourly vs plan) - P2
- [ ] Calculated fields / custom formulas in reports - P2
- [ ] Multi-variable calculations (hours × effective rate × commission %) - P2
- [ ] Aggregation at any level (tech, client, service type, date range) - P2
- [ ] Rate plan / contract type as first-class data dimension - P2
- [ ] Historical rate tracking (rate was X on this date) - P2
- [ ] Payroll-ready exports (base + commission breakdown) - P2
- [ ] Custom metrics definition (define your own KPIs) - P2
- [ ] Formula builder for complex business rules - P3
- [ ] Drill-down from summary to line-item detail - P2
- [ ] Data warehouse / OLAP cube for complex analytics - P3
- [ ] API access to raw data for external BI tools - P2

---

## Dashboard Features

### Views
- [ ] Agent list with status - P1
- [ ] Agent detail view - P1
- [ ] Real-time metrics charts - P2
- [ ] Map view (geographic) - P3
- [ ] Network topology view - P3
- [ ] Custom dashboards - P3

### Remote Access
- [ ] Remote terminal (web-based) - P2
- [ ] Remote desktop (RDP/VNC proxy) - P3
- [ ] File manager UI - P3

### Direct Agent Connection (Admin Tunnel)
- [ ] On-demand reverse tunnel to agent - P2
- [ ] Live interactive shell session (not queued commands) - P2
- [ ] Direct command pipe (real-time stdin/stdout/stderr) - P2
- [ ] Point-to-point encrypted tunnel (WireGuard/custom) - P3
- [ ] Tunnel enables direct SSH/RDP through agent - P3
- [ ] Credential/role-based access (only authorized admins) - P1
- [ ] Agent classification determines tunnel capability - P2
- [ ] Session recording for audit - P2
- [ ] Idle timeout and forced disconnect - P2
- [ ] Concurrent session limits - P3
- [ ] Tunnel through site proxy (when agent behind NAT) - P3
- [ ] Local port forwarding through tunnel - P3

### User Experience & Interface Design

#### Design Philosophy
- Beautiful AND functional - no compromise, no "ugly but it works"
- Clean, modern aesthetic with purposeful whitespace
- Information density without clutter
- Consistent design language across all modules
- Accessibility (WCAG compliance, screen readers, keyboard nav)

#### Customization
- [ ] Dark/light/system theme - P2
- [ ] Customizable dashboard layouts (drag-and-drop widgets) - P2
- [ ] User-defined color accents/branding - P2
- [ ] Configurable data density (compact/comfortable/spacious) - P2
- [ ] Saved views and workspace layouts - P2
- [ ] Per-user preferences synced across devices - P2
- [ ] Custom CSS injection for white-label deployments - P3

#### Real-Time Updates
- [ ] WebSocket-based live data (no page refresh) - P1
- [ ] Real-time agent status changes - P1
- [ ] Live metric updates on dashboards - P1
- [ ] Instant alert notifications (toast/badge) - P1
- [ ] Collaborative indicators (who else is viewing this ticket) - P3
- [ ] Optimistic UI updates (instant feedback, sync in background) - P2

#### Third-Party Module Integration
- [ ] Plugin/module API for UI extensions - P2
- [ ] Dashboard widget SDK (third parties can add widgets) - P2
- [ ] Panel embedding (iframe or native component) - P2
- [ ] Unified navigation (third-party modules appear native) - P2
- [ ] Shared authentication context - P2
- [ ] Event bus for cross-module communication - P2
- [ ] Style guide/component library for consistent third-party UI - P2

#### Core UX
- [ ] Mobile responsive (PWA capable) - P2
- [ ] Keyboard shortcuts with command palette (Cmd+K) - P2
- [ ] Saved searches/filters - P2
- [ ] Bulk selection and actions - P2
- [ ] Contextual right-click menus - P3
- [ ] Undo/redo for destructive actions - P2
- [ ] Breadcrumb navigation - P1
- [ ] Global search (agents, tickets, customers, docs) - P1

### Customer Portal (End-User Facing)
- [ ] Branded portal per customer (white-label) - P2
- [ ] Ticket submission and tracking - P1
- [ ] View open/closed ticket history - P1
- [ ] Asset inventory view (their devices) - P2
- [ ] Service status dashboard (are things healthy?) - P2
- [ ] Meaningful metrics (uptime, response times, SLA status) - P2
- [ ] Invoice/billing history - P3
- [ ] Knowledge base / self-service articles - P2
- [ ] Scheduled maintenance notifications - P2
- [ ] Contact directory (who to call for what) - P2
- [ ] Document library (contracts, policies, procedures) - P3
- [ ] Approval workflows (quote approvals, change requests) - P3
- [ ] Mobile-friendly / PWA - P2

---

## Integration Features

### PSA/Ticketing Integration (External)
- [ ] ConnectWise Manage - P3
- [ ] Autotask - P3
- [ ] HaloPSA - P3
- [ ] Generic webhook for tickets - P2
- [ ] Pluggable PSA adapter architecture - P2

### GuruPSA (Companion CRM/PSA) - Separate Project
- [ ] Core ticketing system - P1
- [ ] Customer/company management - P1
- [ ] Contact management - P1
- [ ] Asset linking (from RMM) - P1
- [ ] Time tracking - P2
- [ ] Contracts/SLA management - P2
- [ ] Quoting/proposals - P3
- [ ] Project management - P3
- [ ] Knowledge base - P2
- [ ] Technician mobile app - P3
- [ ] Calendar/scheduling - P3
- [ ] Email integration (ticket from email) - P1
- [ ] Alert-to-ticket automation - P1
- [ ] Shared reporting engine with RMM - P1

### Automated Usage-Based Billing (GuruPSA + RMM Integration)
No more manual agent counting. Usage data flows automatically to invoices.

#### Core Billing Engine
- [ ] Recurring invoice generation - P2
- [ ] Usage metering framework (count anything, bill for it) - P2
- [ ] Billing rules engine (per-agent, per-user, tiered, flat) - P2
- [ ] Proration for mid-cycle changes - P2
- [ ] Invoice approval workflow (review before send) - P2
- [ ] Multi-currency support - P3
- [ ] Tax calculation / integration - P3
- [ ] Payment gateway integration (Stripe, QuickBooks, etc.) - P2

#### RMM-to-Invoice Automation
- [ ] Live agent count per customer - P1
- [ ] Auto-sync agent count to invoice line items - P2
- [ ] Agent add/remove reflected immediately in billing - P2
- [ ] Billable vs non-billable agent classification - P2
- [ ] Per-agent-type pricing (server vs workstation) - P2
- [ ] Audit trail (agent added on X date, removed on Y) - P2
- [ ] Usage snapshots for billing period - P2
- [ ] Dispute resolution (customer says "I only had 10") - P2

#### Third-Party Usage Integration
- [ ] Generic API adapter for usage data - P2
- [ ] MSP Backup integration (licenses, storage used) - P2
- [ ] Microsoft 365 license count (via Graph API) - P2
- [ ] Google Workspace license count - P3
- [ ] DNS/domain registrar counts - P3
- [ ] Security product license counts - P3
- [ ] Storage/bandwidth metering - P3
- [ ] Custom API connector builder - P3

#### Billing Intelligence
- [ ] Usage trending (predict next invoice) - P3
- [ ] Anomaly alerts (sudden agent spike/drop) - P2
- [ ] Margin analysis per customer - P3
- [ ] Contract vs actual usage comparison - P2
- [ ] Unbilled usage warnings - P2

### Unified API Architecture
- [ ] RESTful API for all RMM functions - P1
- [ ] RESTful API for all PSA functions - P1
- [ ] OpenAPI/Swagger documentation - P1
- [ ] Webhook system (outbound events) - P2
- [ ] API versioning strategy - P1
- [ ] Rate limiting and quotas - P2
- [ ] API key management - P1
- [ ] OAuth2 for third-party integrations - P2
- [ ] GraphQL endpoint (optional) - P3
- [ ] Event-driven architecture (pub/sub) - P2
- [ ] Integration SDK/client libraries - P3

### Documentation
- [ ] IT Glue integration - P3
- [ ] Hudu integration - P3
- [ ] Auto-document discovered info - P3

### Backup
- [ ] Veeam status monitoring - P3
- [ ] Datto status monitoring - P3
- [ ] Generic backup job monitoring - P2

### Network
- [ ] SNMP monitoring - P3
- [ ] Network device discovery - P3
- [ ] Bandwidth monitoring - P3

---

## Security Features

### Endpoint Security
- [ ] Antivirus status monitoring - P2
- [ ] Windows Defender management - P2
- [ ] Firewall status - P2
- [ ] Security baseline compliance - P3
- [ ] Vulnerability scanning integration - P3

### Audit & Compliance
- [ ] Full audit trail - P1
- [ ] Session recording - P3
- [ ] Compliance reporting (SOC2, etc.) - P3
- [ ] Data retention policies - P2

### Agent Security Hardening (P1 post-alpha)
- [ ] Dependency vulnerability scanning (CI/CD pipeline) - P1
- [ ] Automated CVE monitoring for all dependencies - P1
- [ ] Regular security audits of agent codebase - P1
- [ ] Minimal attack surface (no unnecessary open ports) - P1
- [ ] Code signing for agent binaries - P1
- [ ] Secure update mechanism (signed updates only) - P1
- [ ] Memory-safe language benefits (Rust) - P1
- [ ] Principle of least privilege (drop privs where possible) - P1
- [ ] Certificate pinning for server communication - P2
- [ ] Tamper detection (agent integrity monitoring) - P2
- [ ] Sandboxed command execution option - P3
- [ ] Security disclosure program / responsible disclosure policy - P2
- [ ] Penetration testing (periodic) - P2
- [ ] SBOM (Software Bill of Materials) for transparency - P2
- [ ] Rapid patch deployment capability - P1

---

## Infrastructure

### Deployment

#### Development/Small Scale
- [ ] Docker Compose deployment - P1
- [ ] Single-server setup (dev, small MSP <500 agents) - P1

#### Production/Cloud Scale
- [ ] Kubernetes deployment - P2
- [ ] Cloud-native architecture (AWS, Azure, GCP) - P2
- [ ] Horizontal scaling (stateless API servers) - P2
- [ ] Auto-scaling based on load - P2
- [ ] High availability (multi-zone, failover) - P2
- [ ] Load balancing (API, WebSocket, dashboard) - P2
- [ ] Geographic distribution (multi-region) - P3
- [ ] CDN for dashboard/static assets - P2
- [ ] Managed database services (RDS, Cloud SQL) - P2
- [ ] Message queue for agent check-ins (Redis, RabbitMQ, SQS) - P2
- [ ] Connection pooling for 50k+ concurrent agents - P2
- [ ] Read replicas for reporting/analytics queries - P2
- [ ] Tenant isolation (multi-tenant SaaS) - P3

### Code Signing & Distribution (Pre-Release)
- [ ] Windows EV Code Signing Certificate - P1 (pre-release)
  - Required for SmartScreen reputation
  - ~$400-600/year (DigiCert, Sectigo, GlobalSign)
  - Hardware token required for private key
- [ ] Apple Developer Program enrollment - P1 (pre-release)
  - $99/year - covers macOS signing and notarization
  - Required for Gatekeeper approval on macOS 10.15+
- [ ] Signing pipeline integration (CI/CD) - P1 (pre-release)
- [ ] Notarization workflow for macOS builds - P1 (pre-release)
- [ ] Secure key storage (HSM or hardware token) - P1 (pre-release)

### Data
- [ ] PostgreSQL backend - P1
- [ ] Redis caching - P2
- [ ] Time-series DB for metrics (InfluxDB/TimescaleDB) - P2
- [ ] Data archival/retention - P2
- [ ] Backup/restore - P1

---

## Platform Support

### Agent Platforms
- [ ] Windows (x64) - P1
- [ ] Windows (ARM64) - P3
- [ ] Linux (x64) - P1
- [ ] Linux (ARM64) - P2
- [ ] macOS (Intel) - P2
- [ ] macOS (Apple Silicon) - P2
- [ ] FreeBSD - P3

### Mobile Device Management (MDM)
- [ ] iOS/iPadOS agent (MDM profile-based) - P2
- [ ] Android agent (Work Profile / Device Admin) - P2
- [ ] Mobile device inventory - P2
- [ ] App deployment/management - P3
- [ ] Remote lock/wipe - P2
- [ ] Location tracking (with consent) - P3
- [ ] Compliance policies (PIN, encryption) - P2
- [ ] BYOD vs corporate device handling - P3
- [ ] Apple Business Manager integration - P3
- [ ] Android Enterprise integration - P3
- [ ] Mobile management dashboard - P2
- [ ] Push notification for alerts - P2

### Appliance/NAS Agents
- [ ] Unraid plugin - P2
- [ ] Synology package (DSM) - P2
- [ ] QNAP package (QTS) - P3
- [ ] TrueNAS plugin - P3
- [ ] Netgear ReadyNAS (limited/polling) - P3
- [ ] Docker container agent (for containerized appliances) - P2
- [ ] SNMP-based monitoring (for appliances without agent support) - P2
- [ ] Proxmox integration - P2
- [ ] ESXi/vSphere monitoring - P3

### Appliance-Specific Metrics
- [ ] RAID/array health status - P2
- [ ] Drive temperatures and SMART data - P2
- [ ] Share/volume utilization - P2
- [ ] Replication/sync job status - P3
- [ ] UPS status (NUT integration) - P2
- [ ] Docker container status (for Unraid/NAS) - P2
- [ ] VM status (Proxmox/ESXi) - P3
- [ ] Backup job status - P2

### Installation Methods
- [ ] MSI installer (Windows) - P1
- [ ] DEB package (Debian/Ubuntu) - P2
- [ ] RPM package (RHEL/Fedora) - P2
- [ ] Homebrew (macOS) - P3
- [ ] One-liner install script - P1

---

## Future Considerations

### AI/Automation

#### Ticket Intelligence (P2)
- [ ] Grammar/spelling correction for technician notes
- [ ] Professional tone enhancement (convert shorthand to proper language)
- [ ] Auto-summarization of long ticket threads
- [ ] Smart ticket categorization/tagging based on content
- [ ] Duplicate/related ticket detection (3 people report same issue → merge offer)

#### Troubleshooting Assistant (P2)
- [ ] Suggest solutions based on similar past tickets
- [ ] Pattern matching on ticket subject/description
- [ ] Alert-to-resolution correlation (what fixed this alert before?)
- [ ] Knowledge base article suggestions
- [ ] "This issue was resolved X times before by doing Y"

#### Proactive Intelligence (P3)
- [ ] Anomaly detection (ML-based)
- [ ] Auto-remediation scripts (with approval workflow)
- [ ] Natural language queries ("show me servers with high CPU this week")
- [ ] Predictive alerting (disk will be full in 3 days based on trend)

### Advanced Features
- [ ] Asset lifecycle management - P3
- [ ] License management - P3
- [ ] Cost tracking/billing - P3
- [ ] API for third-party integrations - P2

(White-labeling moved to Core Agent Features → White-Labeling / Branding)

---

## Development Phases

### Phase 1: Foundation (MVP)
Core RMM functionality - enough to monitor your own clients.
- Agent: heartbeat, basic metrics (CPU, RAM, disk), Windows + Linux
- Server: agent registration, API, database
- Dashboard: agent list, status, basic metrics view
- Alerts: threshold-based, email notification

### Phase 2: Operational
Day-to-day MSP operations.
- Remote commands, PowerShell/Bash execution
- Patch status, software inventory
- Alert escalation, maintenance windows
- Basic reporting

### Phase 3: PSA Integration
GuruPSA companion or third-party PSA.
- Ticketing, customer management
- Alert-to-ticket automation
- Time tracking, basic billing
- Customer portal

### Phase 4: Scale & Polish
Production-ready for broader use.
- Cloud deployment, horizontal scaling
- Advanced reporting, usage-based billing
- UI polish, customization
- Third-party integrations, plugin SDK

### Phase 5: Intelligence
Differentiation features.
- AI ticket enhancement, troubleshooting suggestions
- Anomaly detection, predictive alerting
- Advanced analytics

---

## Design Principles

### True Integration, Not API Checkboxes
Unlike vendors who claim "API integration" but deliver siloed products that barely talk to each other, GuruRMM and GuruPSA must be designed as a unified system:

- **Single Action, Full Workflow**: When an admin initiates an EDR scan from the RMM, the PSA should automatically:
  - Create/update a ticket with scan status
  - Log the action against the asset
  - Update documentation with findings
  - Trigger alerts/escalations based on results
  - No manual steps, no copy-paste, no "check the other product"

- **Bidirectional Context**: A technician viewing a ticket should see:
  - Real-time agent status
  - Recent alerts and metrics
  - One-click remote access
  - Full asset history
  - Not just a link to "go look it up in the RMM"

- **Event-Driven Architecture**: Actions in one product automatically trigger appropriate responses in others. Not "you can build it yourself with the API" - it works out of the box.

- **Shared Data Model**: Assets, customers, contacts, and history exist once and are referenced everywhere. No sync conflicts, no duplicate data entry.

### Avoid the Datto Anti-Pattern
Datto owns ITGlue, Autotask, DattoRMM, and EDR - yet they operate as separate products that happen to have APIs. Example failures to avoid:
- EDR scan results don't auto-create tickets
- RMM alerts require manual ticket creation
- Documentation requires separate manual updates
- "Integration" means "we have an API, build it yourself"

GuruRMM/GuruPSA should feel like one product with different views, not two products bolted together.

---

## Notes

Add feature ideas and notes here as they come up:

- GuruPSA will be a separate repo but designed to integrate seamlessly with GuruRMM
- API-first design: both products should be fully controllable via API
- Users can use GuruRMM standalone, GuruPSA standalone, or both together
- Third-party PSA users get first-class integration via pluggable adapters
- Consider shared authentication/SSO between RMM and PSA

## Project Structure

```
GuruRMM (this repo)
├── agent/        - Rust agent for endpoints
├── server/       - Rust API server
├── dashboard/    - React web dashboard
└── docs/         - Documentation

GuruPSA (future repo)
├── server/       - API server (Rust or Node?)
├── dashboard/    - React web dashboard
├── portal/       - Customer portal
└── docs/         - Documentation

Shared
├── guru-api-sdk/ - Client libraries for API
└── guru-common/  - Shared types/utilities
```

---

*Last updated: 2025-12-15*


Now let me check the recent session logs and explore more components:


Bash

ls -lart "C:\Users\MikeSwanson\claude-projects\gururmm\session-logs" | tail -5


total 20
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 4451 Dec 20 17:55 2025-12-20-v040-build.md
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 6698 Dec 20 17:55 2025-12-15-build-server-setup.md
drwxr-xr-x 1 AzureAD+MikeSwanson 4096    0 Dec 20 17:55 ./
drwxr-xr-x 1 AzureAD+MikeSwanson 4096    0 Jan  8 08:07 ../


     1→# Session Log: GuruRMM v0.4.0 Build with Tray Icon
     2→**Date:** 2025-12-20
     3→**Focus:** Tray icon implementation, cross-platform builds
     4→
     5→---
     6→
     7→## Summary
     8→
     9→Built GuruRMM v0.4.0 with new system tray application for Windows.
    10→
    11→### Completed
    12→
    13→1. **Tray Icon Implementation** (from previous session)
    14→   - IPC infrastructure in `agent/src/ipc.rs` (Named Pipe for Windows)
    15→   - TrayPolicy struct for admin-controlled visibility
    16→   - Tray app crate with menu, icon states, IPC client
    17→   - SVG icon assets (green/yellow/red/gray states)
    18→
    19→2. **Compilation Fixes**
    20→   - Fixed `device_id::get_device_id()` return type (String, not Result)
    21→   - Added `TrayPolicyUpdate` match arm in WebSocket handler
    22→   - Added `last_checkin` and `tray_policy` fields to Windows service AppState
    23→   - Fixed tray-icon API change (`set_menu` returns unit now)
    24→
    25→3. **Cross-Platform Builds**
    26→   - Installed mingw-w64 via Homebrew on Mac
    27→   - Added `x86_64-pc-windows-gnu` target to Rust
    28→   - Configured cargo for Windows cross-compilation
    29→
    30→### Build Results (v0.4.0)
    31→
    32→| Component | Target | Size | Location |
    33→|-----------|--------|------|----------|
    34→| Agent | Linux x86_64 | 3.3 MB | Build server: `~/gururmm/agent/target/release/gururmm-agent` |
    35→| Agent | Windows x64 | 2.8 MB | Local: `agent/target/x86_64-pc-windows-gnu/release/gururmm-agent.exe` |
    36→| Tray App | Windows x64 | 1.6 MB | Local: `tray/target/x86_64-pc-windows-gnu/release/gururmm-tray.exe` |
    37→
    38→---
    39→
    40→## Architecture
    41→
    42→```
    43→┌─────────────────┐     Policy      ┌─────────────────┐
    44→│   RMM Server    │ ──────────────► │  Agent Service  │
    45→│  (WebSocket)    │                 │  (Background)   │
    46→└─────────────────┘                 └────────┬────────┘
    47→                                             │ IPC
    48→                                             │ (Named Pipe)
    49→                                             ▼
    50→                                    ┌─────────────────┐
    51→                                    │   Tray App      │
    52→                                    │  (User Session) │
    53→                                    └─────────────────┘
    54→```
    55→
    56→- Named pipe: `\\.\pipe\gururmm-agent`
    57→- Agent runs as SYSTEM, tray runs in user session
    58→- Policy controls: visibility, menu items, allowed actions
    59→
    60→---
    61→
    62→## Key Files
    63→
    64→### New Files
    65→- `agent/src/ipc.rs` - Named pipe IPC server, TrayPolicy, AgentStatus
    66→- `tray/Cargo.toml` - Tray app crate config
    67→- `tray/src/main.rs` - Entry point
    68→- `tray/src/tray.rs` - Tray icon management
    69→- `tray/src/menu.rs` - Dynamic menu building
    70→- `tray/src/ipc.rs` - Named pipe client
    71→- `assets/icons/*.svg` - Tray icon states
    72→
    73→### Modified Files
    74→- `agent/Cargo.toml` - Version 0.4.0, Windows IPC features
    75→- `agent/src/main.rs` - IPC server integration, AppState fields
    76→- `agent/src/service.rs` - Added last_checkin, tray_policy to AppState
    77→- `agent/src/transport/mod.rs` - Added TrayPolicyUpdate to ServerMessage
    78→- `agent/src/transport/websocket.rs` - Handle TrayPolicyUpdate
    79→
    80→---
    81→
    82→## Build Server (172.16.3.30)
    83→
    84→- **SSH:** `guru@172.16.3.30` or `root@172.16.3.30`
    85→- **Rust:** Installed via rustup
    86→- **Note:** Requires sudo for apt (password needed)
    87→- **Linux binary:** `~/gururmm/agent/target/release/gururmm-agent`
    88→
    89→### Cross-Compile from Mac
    90→```bash
    91→# Windows agent
    92→cd agent && cargo build --release --target x86_64-pc-windows-gnu
    93→
    94→# Windows tray
    95→cd tray && cargo build --release --target x86_64-pc-windows-gnu
    96→```
    97→
    98→---
    99→
   100→## Pending Tasks
   101→
   102→1. **Deploy Windows binaries** to downloads server
   103→2. **Implement tray launcher** in agent (auto-launch in user sessions)
   104→3. **Add TrayPolicy to server** data model and site settings API
   105→4. **Dashboard UI** for tray policy management
   106→5. **Mac/Linux tray support** (Unix domain socket instead of named pipe)
   107→
   108→---
   109→
   110→## Credentials Reference
   111→
   112→### Build Server (172.16.3.30)
   113→- SSH: guru/root with key
   114→- PostgreSQL: gururmm / gururmm / 43617ebf7eb242e814ca9988cc4df5ad
   115→
   116→### Site Code
   117→- Main Office: `SWIFT-CLOUD-6910`
   118→
   119→### URLs
   120→- Dashboard: https://rmm-api.azcomputerguru.com/
   121→- API: https://rmm-api.azcomputerguru.com/api/
   122→- WebSocket: wss://rmm-api.azcomputerguru.com/ws
   123→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

# Session Log: GuruRMM v0.4.0 Build with Tray Icon
**Date:** 2025-12-20
**Focus:** Tray icon implementation, cross-platform builds

---

## Summary

Built GuruRMM v0.4.0 with new system tray application for Windows.

### Completed

1. **Tray Icon Implementation** (from previous session)
   - IPC infrastructure in `agent/src/ipc.rs` (Named Pipe for Windows)
   - TrayPolicy struct for admin-controlled visibility
   - Tray app crate with menu, icon states, IPC client
   - SVG icon assets (green/yellow/red/gray states)

2. **Compilation Fixes**
   - Fixed `device_id::get_device_id()` return type (String, not Result)
   - Added `TrayPolicyUpdate` match arm in WebSocket handler
   - Added `last_checkin` and `tray_policy` fields to Windows service AppState
   - Fixed tray-icon API change (`set_menu` returns unit now)

3. **Cross-Platform Builds**
   - Installed mingw-w64 via Homebrew on Mac
   - Added `x86_64-pc-windows-gnu` target to Rust
   - Configured cargo for Windows cross-compilation

### Build Results (v0.4.0)

| Component | Target | Size | Location |
|-----------|--------|------|----------|
| Agent | Linux x86_64 | 3.3 MB | Build server: `~/gururmm/agent/target/release/gururmm-agent` |
| Agent | Windows x64 | 2.8 MB | Local: `agent/target/x86_64-pc-windows-gnu/release/gururmm-agent.exe` |
| Tray App | Windows x64 | 1.6 MB | Local: `tray/target/x86_64-pc-windows-gnu/release/gururmm-tray.exe` |

---

## Architecture

```
┌─────────────────┐     Policy      ┌─────────────────┐
│   RMM Server    │ ──────────────► │  Agent Service  │
│  (WebSocket)    │                 │  (Background)   │
└─────────────────┘                 └────────┬────────┘
                                             │ IPC
                                             │ (Named Pipe)
                                             ▼
                                    ┌─────────────────┐
                                    │   Tray App      │
                                    │  (User Session) │
                                    └─────────────────┘
```

- Named pipe: `\\.\pipe\gururmm-agent`
- Agent runs as SYSTEM, tray runs in user session
- Policy controls: visibility, menu items, allowed actions

---

## Key Files

### New Files
- `agent/src/ipc.rs` - Named pipe IPC server, TrayPolicy, AgentStatus
- `tray/Cargo.toml` - Tray app crate config
- `tray/src/main.rs` - Entry point
- `tray/src/tray.rs` - Tray icon management
- `tray/src/menu.rs` - Dynamic menu building
- `tray/src/ipc.rs` - Named pipe client
- `assets/icons/*.svg` - Tray icon states

### Modified Files
- `agent/Cargo.toml` - Version 0.4.0, Windows IPC features
- `agent/src/main.rs` - IPC server integration, AppState fields
- `agent/src/service.rs` - Added last_checkin, tray_policy to AppState
- `agent/src/transport/mod.rs` - Added TrayPolicyUpdate to ServerMessage
- `agent/src/transport/websocket.rs` - Handle TrayPolicyUpdate

---

## Build Server (172.16.3.30)

- **SSH:** `guru@172.16.3.30` or `root@172.16.3.30`
- **Rust:** Installed via rustup
- **Note:** Requires sudo for apt (password needed)
- **Linux binary:** `~/gururmm/agent/target/release/gururmm-agent`

### Cross-Compile from Mac
```bash
# Windows agent
cd agent && cargo build --release --target x86_64-pc-windows-gnu

# Windows tray
cd tray && cargo build --release --target x86_64-pc-windows-gnu
```

---

## Pending Tasks

1. **Deploy Windows binaries** to downloads server
2. **Implement tray launcher** in agent (auto-launch in user sessions)
3. **Add TrayPolicy to server** data model and site settings API
4. **Dashboard UI** for tray policy management
5. **Mac/Linux tray support** (Unix domain socket instead of named pipe)

---

## Credentials Reference

### Build Server (172.16.3.30)
- SSH: guru/root with key
- PostgreSQL: gururmm / gururmm / 43617ebf7eb242e814ca9988cc4df5ad

### Site Code
- Main Office: `SWIFT-CLOUD-6910`

### URLs
- Dashboard: https://rmm-api.azcomputerguru.com/
- API: https://rmm-api.azcomputerguru.com/api/
- WebSocket: wss://rmm-api.azcomputerguru.com/ws


Let me check for package.json files and more API details:


     1→{
     2→  "name": "dashboard",
     3→  "private": true,
     4→  "version": "0.2.0",
     5→  "type": "module",
     6→  "scripts": {
     7→    "dev": "vite",
     8→    "build": "tsc -b && vite build",
     9→    "lint": "eslint .",
    10→    "preview": "vite preview"
    11→  },
    12→  "dependencies": {
    13→    "@tanstack/react-query": "^5.90.12",
    14→    "axios": "^1.13.2",
    15→    "clsx": "^2.1.1",
    16→    "lucide-react": "^0.561.0",
    17→    "react": "^19.2.0",
    18→    "react-dom": "^19.2.0",
    19→    "react-router-dom": "^7.10.1",
    20→    "recharts": "^3.6.0",
    21→    "tailwind-merge": "^3.4.0"
    22→  },
    23→  "devDependencies": {
    24→    "@eslint/js": "^9.39.1",
    25→    "@tailwindcss/vite": "^4.1.18",
    26→    "@types/node": "^24.10.1",
    27→    "@types/react": "^19.2.5",
    28→    "@types/react-dom": "^19.2.3",
    29→    "@vitejs/plugin-react": "^5.1.1",
    30→    "autoprefixer": "^10.4.22",
    31→    "eslint": "^9.39.1",
    32→    "eslint-plugin-react-hooks": "^7.0.1",
    33→    "eslint-plugin-react-refresh": "^0.4.24",
    34→    "globals": "^16.5.0",
    35→    "postcss": "^8.5.6",
    36→    "tailwindcss": "^4.1.18",
    37→    "typescript": "~5.9.3",
    38→    "typescript-eslint": "^8.46.4",
    39→    "vite": "^7.2.4"
    40→  }
    41→}
    42→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>


     1→[package]
     2→name = "gururmm-agent"
     3→version = "0.5.1"
     4→edition = "2021"
     5→description = "GuruRMM Agent - Cross-platform RMM agent"
     6→authors = ["GuruRMM"]
     7→
     8→[features]
     9→default = ["native-service"]
    10→# Modern Windows (10+, Server 2016+): Native Windows Service integration
    11→native-service = ["dep:windows-service", "dep:windows"]
    12→# Legacy Windows (7, Server 2008 R2): Console mode, use NSSM for service wrapper
    13→legacy = []
    14→
    15→[dependencies]
    16→# Async runtime
    17→tokio = { version = "1", features = ["full"] }
    18→
    19→# System information (cross-platform metrics)
    20→sysinfo = "0.31"
    21→
    22→# WebSocket client (native-tls for Windows 7/2008R2 compatibility)
    23→tokio-tungstenite = { version = "0.24", features = ["native-tls"] }
    24→futures-util = "0.3"
    25→
    26→# HTTP client (fallback/registration) - native-tls for Windows 7/2008R2 compatibility
    27→reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] }
    28→
    29→# Serialization
    30→serde = { version = "1", features = ["derive"] }
    31→serde_json = "1"
    32→toml = "0.8"
    33→
    34→# CLI arguments
    35→clap = { version = "4", features = ["derive"] }
    36→
    37→# Logging
    38→tracing = "0.1"
    39→tracing-subscriber = { version = "0.3", features = ["env-filter"] }
    40→
    41→# Error handling
    42→anyhow = "1"
    43→thiserror = "1"
    44→
    45→# UUID for identifiers
    46→uuid = { version = "1", features = ["v4", "serde"] }
    47→
    48→# SHA256 checksums for update verification
    49→sha2 = "0.10"
    50→
    51→# Time handling
    52→chrono = { version = "0.4", features = ["serde"] }
    53→
    54→# Hostname detection
    55→hostname = "0.4"
    56→
    57→# Network interface enumeration (LAN IPs)
    58→local-ip-address = "0.6"
    59→
    60→# Async file operations
    61→tokio-util = "0.7"
    62→
    63→[target.'cfg(windows)'.dependencies]
    64→# Windows service support (optional, only for native-service feature)
    65→windows-service = { version = "0.7", optional = true }
    66→# Windows-specific APIs for service management and IPC (optional for native-service)
    67→windows = { version = "0.58", optional = true, features = [
    68→    "Win32_System_Services",
    69→    "Win32_Foundation",
    70→    "Win32_Security",
    71→    "Win32_System_Pipes",
    72→    "Win32_Storage_FileSystem",
    73→    "Win32_System_IO",
    74→    "Win32_System_RemoteDesktop",
    75→    "Win32_System_Threading",
    76→    "Win32_System_StationsAndDesktops",
    77→    "Win32_UI_WindowsAndMessaging",
    78→] }
    79→
    80→[target.'cfg(unix)'.dependencies]
    81→# Unix signal handling and user detection
    82→nix = { version = "0.29", features = ["signal", "user"] }
    83→
    84→[profile.release]
    85→# Optimize for size while maintaining performance
    86→opt-level = "z"
    87→lto = true
    88→codegen-units = 1
    89→strip = true
    90→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

[package]
name = "gururmm-agent"
version = "0.5.1"
edition = "2021"
description = "GuruRMM Agent - Cross-platform RMM agent"
authors = ["GuruRMM"]

[features]
default = ["native-service"]
# Modern Windows (10+, Server 2016+): Native Windows Service integration
native-service = ["dep:windows-service", "dep:windows"]
# Legacy Windows (7, Server 2008 R2): Console mode, use NSSM for service wrapper
legacy = []

[dependencies]
# Async runtime
tokio = { version = "1", features = ["full"] }

# System information (cross-platform metrics)
sysinfo = "0.31"

# WebSocket client (native-tls for Windows 7/2008R2 compatibility)
tokio-tungstenite = { version = "0.24", features = ["native-tls"] }
futures-util = "0.3"

# HTTP client (fallback/registration) - native-tls for Windows 7/2008R2 compatibility
reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] }

# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml = "0.8"

# CLI arguments
clap = { version = "4", features = ["derive"] }

# Logging
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

# Error handling
anyhow = "1"
thiserror = "1"

# UUID for identifiers
uuid = { version = "1", features = ["v4", "serde"] }

# SHA256 checksums for update verification
sha2 = "0.10"

# Time handling
chrono = { version = "0.4", features = ["serde"] }

# Hostname detection
hostname = "0.4"

# Network interface enumeration (LAN IPs)
local-ip-address = "0.6"

# Async file operations
tokio-util = "0.7"

[target.'cfg(windows)'.dependencies]
# Windows service support (optional, only for native-service feature)
windows-service = { version = "0.7", optional = true }
# Windows-specific APIs for service management and IPC (optional for native-service)
windows = { version = "0.58", optional = true, features = [
    "Win32_System_Services",
    "Win32_Foundation",
    "Win32_Security",
    "Win32_System_Pipes",
    "Win32_Storage_FileSystem",
    "Win32_System_IO",
    "Win32_System_RemoteDesktop",
    "Win32_System_Threading",
    "Win32_System_StationsAndDesktops",
    "Win32_UI_WindowsAndMessaging",
] }

[target.'cfg(unix)'.dependencies]
# Unix signal handling and user detection
nix = { version = "0.29", features = ["signal", "user"] }

[profile.release]
# Optimize for size while maintaining performance
opt-level = "z"
lto = true
codegen-units = 1
strip = true


Let me check the API details and database models more thoroughly:


total 128
drwxr-xr-x 1 AzureAD+MikeSwanson 4096     0 Dec 21 17:30 ./
drwxr-xr-x 1 AzureAD+MikeSwanson 4096     0 Dec 21 17:28 ../
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 10902 Dec 20 17:55 agents.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 17341 Dec 21 15:24 alerts.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  4301 Dec 20 17:55 clients.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  4159 Dec 20 17:55 commands.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  9126 Dec 21 12:28 metrics.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096   599 Dec 21 17:29 mod.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 16471 Dec 21 15:22 policies.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  7972 Dec 20 17:55 sites.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  5781 Dec 20 17:55 updates.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  8301 Dec 21 17:30 user_organizations.rs
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  5036 Dec 21 09:47 users.rs


     1→//! Agent database operations
     2→
     3→use chrono::{DateTime, Utc};
     4→use serde::{Deserialize, Serialize};
     5→use sqlx::PgPool;
     6→use uuid::Uuid;
     7→
     8→/// Agent record from database
     9→#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
    10→pub struct Agent {
    11→    pub id: Uuid,
    12→    pub hostname: String,
    13→    #[serde(skip_serializing)]
    14→    pub api_key_hash: Option<String>,  // Nullable: new agents use site's api_key
    15→    pub os_type: String,
    16→    pub os_version: Option<String>,
    17→    pub agent_version: Option<String>,
    18→    pub last_seen: Option<DateTime<Utc>>,
    19→    pub status: String,
    20→    pub created_at: DateTime<Utc>,
    21→    pub updated_at: DateTime<Utc>,
    22→    // New fields for site-based registration
    23→    pub device_id: Option<String>,     // Hardware-derived unique ID
    24→    pub site_id: Option<Uuid>,         // Which site this agent belongs to
    25→}
    26→
    27→/// Agent without sensitive fields (for API responses)
    28→#[derive(Debug, Clone, Serialize, Deserialize)]
    29→pub struct AgentResponse {
    30→    pub id: Uuid,
    31→    pub hostname: String,
    32→    pub os_type: String,
    33→    pub os_version: Option<String>,
    34→    pub agent_version: Option<String>,
    35→    pub last_seen: Option<DateTime<Utc>>,
    36→    pub status: String,
    37→    pub created_at: DateTime<Utc>,
    38→    pub device_id: Option<String>,
    39→    pub site_id: Option<Uuid>,
    40→    pub site_name: Option<String>,
    41→    pub client_name: Option<String>,
    42→}
    43→
    44→impl From<Agent> for AgentResponse {
    45→    fn from(agent: Agent) -> Self {
    46→        Self {
    47→            id: agent.id,
    48→            hostname: agent.hostname,
    49→            os_type: agent.os_type,
    50→            os_version: agent.os_version,
    51→            agent_version: agent.agent_version,
    52→            last_seen: agent.last_seen,
    53→            status: agent.status,
    54→            created_at: agent.created_at,
    55→            device_id: agent.device_id,
    56→            site_id: agent.site_id,
    57→            site_name: None,
    58→            client_name: None,
    59→        }
    60→    }
    61→}
    62→
    63→/// Create a new agent registration
    64→#[derive(Debug, Clone, Deserialize)]
    65→pub struct CreateAgent {
    66→    pub hostname: String,
    67→    pub api_key_hash: String,
    68→    pub os_type: String,
    69→    pub os_version: Option<String>,
    70→    pub agent_version: Option<String>,
    71→}
    72→
    73→/// Insert a new agent into the database
    74→pub async fn create_agent(pool: &PgPool, agent: CreateAgent) -> Result<Agent, sqlx::Error> {
    75→    sqlx::query_as::<_, Agent>(
    76→        r#"
    77→        INSERT INTO agents (hostname, api_key_hash, os_type, os_version, agent_version, status)
    78→        VALUES ($1, $2, $3, $4, $5, 'offline')
    79→        RETURNING *
    80→        "#,
    81→    )
    82→    .bind(&agent.hostname)
    83→    .bind(&agent.api_key_hash)
    84→    .bind(&agent.os_type)
    85→    .bind(&agent.os_version)
    86→    .bind(&agent.agent_version)
    87→    .fetch_one(pool)
    88→    .await
    89→}
    90→
    91→/// Get an agent by ID
    92→pub async fn get_agent_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Agent>, sqlx::Error> {
    93→    sqlx::query_as::<_, Agent>("SELECT * FROM agents WHERE id = $1")
    94→        .bind(id)
    95→        .fetch_optional(pool)
    96→        .await
    97→}
    98→
    99→/// Get an agent by API key hash
   100→pub async fn get_agent_by_api_key_hash(

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

//! Agent database operations

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use uuid::Uuid;

/// Agent record from database
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
pub struct Agent {
    pub id: Uuid,
    pub hostname: String,
    #[serde(skip_serializing)]
    pub api_key_hash: Option<String>,  // Nullable: new agents use site's api_key
    pub os_type: String,
    pub os_version: Option<String>,
    pub agent_version: Option<String>,
    pub last_seen: Option<DateTime<Utc>>,
    pub status: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    // New fields for site-based registration
    pub device_id: Option<String>,     // Hardware-derived unique ID
    pub site_id: Option<Uuid>,         // Which site this agent belongs to
}

/// Agent without sensitive fields (for API responses)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentResponse {
    pub id: Uuid,
    pub hostname: String,
    pub os_type: String,
    pub os_version: Option<String>,
    pub agent_version: Option<String>,
    pub last_seen: Option<DateTime<Utc>>,
    pub status: String,
    pub created_at: DateTime<Utc>,
    pub device_id: Option<String>,
    pub site_id: Option<Uuid>,
    pub site_name: Option<String>,
    pub client_name: Option<String>,
}

impl From<Agent> for AgentResponse {
    fn from(agent: Agent) -> Self {
        Self {
            id: agent.id,
            hostname: agent.hostname,
            os_type: agent.os_type,
            os_version: agent.os_version,
            agent_version: agent.agent_version,
            last_seen: agent.last_seen,
            status: agent.status,
            created_at: agent.created_at,
            device_id: agent.device_id,
            site_id: agent.site_id,
            site_name: None,
            client_name: None,
        }
    }
}

/// Create a new agent registration
#[derive(Debug, Clone, Deserialize)]
pub struct CreateAgent {
    pub hostname: String,
    pub api_key_hash: String,
    pub os_type: String,
    pub os_version: Option<String>,
    pub agent_version: Option<String>,
}

/// Insert a new agent into the database
pub async fn create_agent(pool: &PgPool, agent: CreateAgent) -> Result<Agent, sqlx::Error> {
    sqlx::query_as::<_, Agent>(
        r#"
        INSERT INTO agents (hostname, api_key_hash, os_type, os_version, agent_version, status)
        VALUES ($1, $2, $3, $4, $5, 'offline')
        RETURNING *
        "#,
    )
    .bind(&agent.hostname)
    .bind(&agent.api_key_hash)
    .bind(&agent.os_type)
    .bind(&agent.os_version)
    .bind(&agent.agent_version)
    .fetch_one(pool)
    .await
}

/// Get an agent by ID
pub async fn get_agent_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Agent>, sqlx::Error> {
    sqlx::query_as::<_, Agent>("SELECT * FROM agents WHERE id = $1")
        .bind(id)
        .fetch_optional(pool)
        .await
}

/// Get an agent by API key hash
pub async fn get_agent_by_api_key_hash(


total 124
drwxr-xr-x 1 AzureAD+MikeSwanson 4096     0 Dec 21 12:32 ./
drwxr-xr-x 1 AzureAD+MikeSwanson 4096     0 Dec 21 09:55 ../
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 16855 Dec 21 12:32 AgentDetail.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 14199 Dec 20 17:55 Agents.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  2948 Dec 21 09:54 AuthCallback.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 11563 Dec 20 17:55 Clients.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  4617 Dec 20 17:55 Commands.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  4955 Dec 20 17:55 Dashboard.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  4669 Dec 21 09:56 Login.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  4219 Dec 20 17:55 Register.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096  9345 Dec 21 09:57 Settings.tsx
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 17203 Dec 20 17:55 Sites.tsx


     1→//! Windows Service implementation for GuruRMM Agent
     2→//!
     3→//! This module implements the Windows Service Control Manager (SCM) protocol,
     4→//! allowing the agent to run as a native Windows service without third-party wrappers.
     5→
     6→#[cfg(all(windows, feature = "native-service"))]
     7→pub mod windows {
     8→    use std::ffi::OsString;
     9→    use std::path::PathBuf;
    10→    use std::sync::mpsc;
    11→    use std::time::Duration;
    12→
    13→    use anyhow::{Context, Result};
    14→    use tracing::{error, info, warn};
    15→    use windows_service::{
    16→        define_windows_service,
    17→        service::{
    18→            ServiceAccess, ServiceControl, ServiceControlAccept, ServiceErrorControl,
    19→            ServiceExitCode, ServiceInfo, ServiceStartType, ServiceState, ServiceStatus,
    20→            ServiceType,
    21→        },
    22→        service_control_handler::{self, ServiceControlHandlerResult},
    23→        service_dispatcher, service_manager::{ServiceManager, ServiceManagerAccess},
    24→    };
    25→
    26→    pub const SERVICE_NAME: &str = "GuruRMMAgent";
    27→    pub const SERVICE_DISPLAY_NAME: &str = "GuruRMM Agent";
    28→    pub const SERVICE_DESCRIPTION: &str =
    29→        "GuruRMM Agent - Remote Monitoring and Management service";
    30→    pub const INSTALL_DIR: &str = r"C:\Program Files\GuruRMM";
    31→    pub const CONFIG_DIR: &str = r"C:\ProgramData\GuruRMM";
    32→
    33→    // Generate the Windows service boilerplate
    34→    define_windows_service!(ffi_service_main, service_main);
    35→
    36→    /// Entry point called by the Windows Service Control Manager
    37→    pub fn run_as_service() -> Result<()> {
    38→        // This function is called when Windows starts the service.
    39→        // It blocks until the service is stopped.
    40→        service_dispatcher::start(SERVICE_NAME, ffi_service_main)
    41→            .context("Failed to start service dispatcher")?;
    42→        Ok(())
    43→    }
    44→
    45→    /// Main service function called by the SCM
    46→    fn service_main(arguments: Vec<OsString>) {
    47→        if let Err(e) = run_service(arguments) {
    48→            error!("Service error: {}", e);
    49→        }
    50→    }
    51→
    52→    /// The actual service implementation
    53→    fn run_service(_arguments: Vec<OsString>) -> Result<()> {
    54→        // Create a channel to receive stop events
    55→        let (shutdown_tx, shutdown_rx) = mpsc::channel();
    56→
    57→        // Create the service control handler
    58→        let event_handler = move |control_event| -> ServiceControlHandlerResult {
    59→            match control_event {
    60→                ServiceControl::Stop => {
    61→                    info!("Received stop command from SCM");
    62→                    let _ = shutdown_tx.send(());
    63→                    ServiceControlHandlerResult::NoError
    64→                }
    65→                ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
    66→                ServiceControl::Shutdown => {
    67→                    info!("Received shutdown command from SCM");
    68→                    let _ = shutdown_tx.send(());
    69→                    ServiceControlHandlerResult::NoError
    70→                }
    71→                _ => ServiceControlHandlerResult::NotImplemented,
    72→            }
    73→        };
    74→
    75→        // Register the service control handler
    76→        let status_handle = service_control_handler::register(SERVICE_NAME, event_handler)
    77→            .context("Failed to register service control handler")?;
    78→
    79→        // Report that we're starting
    80→        status_handle
    81→            .set_service_status(ServiceStatus {
    82→                service_type: ServiceType::OWN_PROCESS,
    83→                current_state: ServiceState::StartPending,
    84→                controls_accepted: ServiceControlAccept::empty(),
    85→                exit_code: ServiceExitCode::Win32(0),
    86→                checkpoint: 0,
    87→                wait_hint: Duration::from_secs(10),
    88→                process_id: None,
    89→            })
    90→            .context("Failed to set StartPending status")?;
    91→
    92→        // Determine config path
    93→        let config_path = PathBuf::from(format!(r"{}\\agent.toml", CONFIG_DIR));
    94→
    95→        // Create the tokio runtime for the agent
    96→        let runtime = tokio::runtime::Runtime::new().context("Failed to create tokio runtime")?;
    97→
    98→        // Start the agent in the runtime
    99→        let agent_result = runtime.block_on(async {
   100→            // Load configuration

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

//! Windows Service implementation for GuruRMM Agent
//!
//! This module implements the Windows Service Control Manager (SCM) protocol,
//! allowing the agent to run as a native Windows service without third-party wrappers.

#[cfg(all(windows, feature = "native-service"))]
pub mod windows {
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::sync::mpsc;
    use std::time::Duration;

    use anyhow::{Context, Result};
    use tracing::{error, info, warn};
    use windows_service::{
        define_windows_service,
        service::{
            ServiceAccess, ServiceControl, ServiceControlAccept, ServiceErrorControl,
            ServiceExitCode, ServiceInfo, ServiceStartType, ServiceState, ServiceStatus,
            ServiceType,
        },
        service_control_handler::{self, ServiceControlHandlerResult},
        service_dispatcher, service_manager::{ServiceManager, ServiceManagerAccess},
    };

    pub const SERVICE_NAME: &str = "GuruRMMAgent";
    pub const SERVICE_DISPLAY_NAME: &str = "GuruRMM Agent";
    pub const SERVICE_DESCRIPTION: &str =
        "GuruRMM Agent - Remote Monitoring and Management service";
    pub const INSTALL_DIR: &str = r"C:\Program Files\GuruRMM";
    pub const CONFIG_DIR: &str = r"C:\ProgramData\GuruRMM";

    // Generate the Windows service boilerplate
    define_windows_service!(ffi_service_main, service_main);

    /// Entry point called by the Windows Service Control Manager
    pub fn run_as_service() -> Result<()> {
        // This function is called when Windows starts the service.
        // It blocks until the service is stopped.
        service_dispatcher::start(SERVICE_NAME, ffi_service_main)
            .context("Failed to start service dispatcher")?;
        Ok(())
    }

    /// Main service function called by the SCM
    fn service_main(arguments: Vec<OsString>) {
        if let Err(e) = run_service(arguments) {
            error!("Service error: {}", e);
        }
    }

    /// The actual service implementation
    fn run_service(_arguments: Vec<OsString>) -> Result<()> {
        // Create a channel to receive stop events
        let (shutdown_tx, shutdown_rx) = mpsc::channel();

        // Create the service control handler
        let event_handler = move |control_event| -> ServiceControlHandlerResult {
            match control_event {
                ServiceControl::Stop => {
                    info!("Received stop command from SCM");
                    let _ = shutdown_tx.send(());
                    ServiceControlHandlerResult::NoError
                }
                ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
                ServiceControl::Shutdown => {
                    info!("Received shutdown command from SCM");
                    let _ = shutdown_tx.send(());
                    ServiceControlHandlerResult::NoError
                }
                _ => ServiceControlHandlerResult::NotImplemented,
            }
        };

        // Register the service control handler
        let status_handle = service_control_handler::register(SERVICE_NAME, event_handler)
            .context("Failed to register service control handler")?;

        // Report that we're starting
        status_handle
            .set_service_status(ServiceStatus {
                service_type: ServiceType::OWN_PROCESS,
                current_state: ServiceState::StartPending,
                controls_accepted: ServiceControlAccept::empty(),
                exit_code: ServiceExitCode::Win32(0),
                checkpoint: 0,
                wait_hint: Duration::from_secs(10),
                process_id: None,
            })
            .context("Failed to set StartPending status")?;

        // Determine config path
        let config_path = PathBuf::from(format!(r"{}\\agent.toml", CONFIG_DIR));

        // Create the tokio runtime for the agent
        let runtime = tokio::runtime::Runtime::new().context("Failed to create tokio runtime")?;

        // Start the agent in the runtime
        let agent_result = runtime.block_on(async {
            // Load configuration


Let me check the git log to see recent work:


d797fd5 feat: Multi-tenant authorization system (Phases 1-2)
4d48849 Implement stackable policy system with alert evaluation
dfc3be1 Add temperature metrics collection and display (v0.5.1)
84253e8 Add Microsoft Entra ID SSO and user management
998f2b3 Add JWT authentication to command and update endpoints
ae8a12a Add POST /api/agents/:id/update endpoint for on-demand updates
4808983 Mark docker-compose.yml as deprecated
0978587 Fix Windows service name in updater module
3c7fed2 Bump agent version to 0.5.0
499c0fd Agent: implement tray launcher for user session integration
c24c48c Add session log: v0.4.0 build with tray icon
f2711de Fix compilation errors for v0.4.0 build
9f24a4e Bump agent version to 0.4.0 (tray support)
60a3df4 Archive tray implementation plan
e70f4d4 Add system tray application with IPC communication
fa9e917 Add PowerShell legacy agent for Windows Server 2008 R2
00027cb Switch to native-tls for Windows 7/2008R2 compatibility
f69fc02 Server v0.2.0: auto-update system with version scanner
b2fe05a Agent v0.3.4: self-update module with auto-rollback
11e50a8 Add extended metrics collection and display


Let me check the structure of API endpoints and web socket code:


total 32
drwxr-xr-x 1 AzureAD+MikeSwanson 4096     0 Dec 21 15:35 ./
drwxr-xr-x 1 AzureAD+MikeSwanson 4096     0 Dec 21 17:28 ../
-rw-r--r-- 1 AzureAD+MikeSwanson 4096 26080 Dec 21 15:35 mod.rs


     1→//! WebSocket handler for agent connections
     2→//!
     3→//! Handles real-time communication with agents including:
     4→//! - Authentication handshake
     5→//! - Metrics ingestion
     6→//! - Command dispatching
     7→//! - Watchdog event handling
     8→
     9→use std::collections::HashMap;
    10→use std::sync::Arc;
    11→
    12→use axum::{
    13→    extract::{
    14→        ws::{Message, WebSocket},
    15→        State, WebSocketUpgrade,
    16→    },
    17→    response::Response,
    18→};
    19→use futures_util::{SinkExt, StreamExt};
    20→use serde::{Deserialize, Serialize};
    21→use tokio::sync::{mpsc, RwLock};
    22→use tracing::{debug, error, info, warn};
    23→use uuid::Uuid;
    24→
    25→use crate::alerts::{evaluate_thresholds, MetricsForEvaluation};
    26→use crate::db;
    27→use crate::AppState;
    28→
    29→/// Connected agents manager
    30→pub struct AgentConnections {
    31→    /// Map of agent ID to sender channel
    32→    connections: HashMap<Uuid, mpsc::Sender<ServerMessage>>,
    33→}
    34→
    35→impl AgentConnections {
    36→    pub fn new() -> Self {
    37→        Self {
    38→            connections: HashMap::new(),
    39→        }
    40→    }
    41→
    42→    /// Add a new agent connection
    43→    pub fn add(&mut self, agent_id: Uuid, tx: mpsc::Sender<ServerMessage>) {
    44→        self.connections.insert(agent_id, tx);
    45→    }
    46→
    47→    /// Remove an agent connection
    48→    pub fn remove(&mut self, agent_id: &Uuid) {
    49→        self.connections.remove(agent_id);
    50→    }
    51→
    52→    /// Send a message to a specific agent
    53→    pub async fn send_to(&self, agent_id: &Uuid, msg: ServerMessage) -> bool {
    54→        if let Some(tx) = self.connections.get(agent_id) {
    55→            tx.send(msg).await.is_ok()
    56→        } else {
    57→            false
    58→        }
    59→    }
    60→
    61→    /// Check if an agent is connected
    62→    pub fn is_connected(&self, agent_id: &Uuid) -> bool {
    63→        self.connections.contains_key(agent_id)
    64→    }
    65→
    66→    /// Get count of connected agents
    67→    pub fn count(&self) -> usize {
    68→        self.connections.len()
    69→    }
    70→}
    71→
    72→impl Default for AgentConnections {
    73→    fn default() -> Self {
    74→        Self::new()
    75→    }
    76→}
    77→
    78→/// Messages from agent to server
    79→#[derive(Debug, Clone, Serialize, Deserialize)]
    80→#[serde(tag = "type", content = "payload")]
    81→#[serde(rename_all = "snake_case")]
    82→pub enum AgentMessage {
    83→    Auth(AuthPayload),
    84→    Metrics(MetricsPayload),
    85→    NetworkState(NetworkStatePayload),
    86→    CommandResult(CommandResultPayload),
    87→    WatchdogEvent(WatchdogEventPayload),
    88→    UpdateResult(UpdateResultPayload),
    89→    Heartbeat,
    90→}
    91→
    92→/// Messages from server to agent
    93→#[derive(Debug, Clone, Serialize, Deserialize)]
    94→#[serde(tag = "type", content = "payload")]
    95→#[serde(rename_all = "snake_case")]
    96→pub enum ServerMessage {
    97→    AuthAck(AuthAckPayload),
    98→    Command(CommandPayload),
    99→    ConfigUpdate(serde_json::Value),
   100→    Update(UpdatePayload),
   101→    Ack { message_id: Option<String> },
   102→    Error { code: String, message: String },
   103→}
   104→
   105→#[derive(Debug, Clone, Serialize, Deserialize)]
   106→pub struct AuthPayload {
   107→    pub api_key: String,
   108→    /// Hardware-derived device ID (for site-based registration)
   109→    #[serde(default)]
   110→    pub device_id: Option<String>,
   111→    pub hostname: String,
   112→    pub os_type: String,
   113→    pub os_version: String,
   114→    pub agent_version: String,
   115→    /// Architecture (amd64, arm64, etc.)
   116→    #[serde(default = "default_arch")]
   117→    pub architecture: String,
   118→    /// Previous version if reconnecting after update
   119→    #[serde(default)]
   120→    pub previous_version: Option<String>,
   121→    /// Update ID if reconnecting after update
   122→    #[serde(default)]
   123→    pub pending_update_id: Option<Uuid>,
   124→}
   125→
   126→fn default_arch() -> String {
   127→    "amd64".to_string()
   128→}
   129→
   130→#[derive(Debug, Clone, Serialize, Deserialize)]
   131→pub struct AuthAckPayload {
   132→    pub success: bool,
   133→    pub agent_id: Option<Uuid>,
   134→    pub error: Option<String>,
   135→}
   136→
   137→#[derive(Debug, Clone, Serialize, Deserialize)]
   138→pub struct MetricsPayload {
   139→    pub timestamp: chrono::DateTime<chrono::Utc>,
   140→    pub cpu_percent: f32,
   141→    pub memory_percent: f32,
   142→    pub memory_used_bytes: u64,
   143→    pub memory_total_bytes: u64,
   144→    pub disk_percent: f32,
   145→    pub disk_used_bytes: u64,
   146→    pub disk_total_bytes: u64,
   147→    pub network_rx_bytes: u64,
   148→    pub network_tx_bytes: u64,
   149→    pub os_type: String,
   150→    pub os_version: String,

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

//! WebSocket handler for agent connections
//!
//! Handles real-time communication with agents including:
//! - Authentication handshake
//! - Metrics ingestion
//! - Command dispatching
//! - Watchdog event handling

use std::collections::HashMap;
use std::sync::Arc;

use axum::{
    extract::{
        ws::{Message, WebSocket},
        State, WebSocketUpgrade,
    },
    response::Response,
};
use futures_util::{SinkExt, StreamExt};
use serde::{Deserialize, Serialize};
use tokio::sync::{mpsc, RwLock};
use tracing::{debug, error, info, warn};
use uuid::Uuid;

use crate::alerts::{evaluate_thresholds, MetricsForEvaluation};
use crate::db;
use crate::AppState;

/// Connected agents manager
pub struct AgentConnections {
    /// Map of agent ID to sender channel
    connections: HashMap<Uuid, mpsc::Sender<ServerMessage>>,
}

impl AgentConnections {
    pub fn new() -> Self {
        Self {
            connections: HashMap::new(),
        }
    }

    /// Add a new agent connection
    pub fn add(&mut self, agent_id: Uuid, tx: mpsc::Sender<ServerMessage>) {
        self.connections.insert(agent_id, tx);
    }

    /// Remove an agent connection
    pub fn remove(&mut self, agent_id: &Uuid) {
        self.connections.remove(agent_id);
    }

    /// Send a message to a specific agent
    pub async fn send_to(&self, agent_id: &Uuid, msg: ServerMessage) -> bool {
        if let Some(tx) = self.connections.get(agent_id) {
            tx.send(msg).await.is_ok()
        } else {
            false
        }
    }

    /// Check if an agent is connected
    pub fn is_connected(&self, agent_id: &Uuid) -> bool {
        self.connections.contains_key(agent_id)
    }

    /// Get count of connected agents
    pub fn count(&self) -> usize {
        self.connections.len()
    }
}

impl Default for AgentConnections {
    fn default() -> Self {
        Self::new()
    }
}

/// Messages from agent to server
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "payload")]
#[serde(rename_all = "snake_case")]
pub enum AgentMessage {
    Auth(AuthPayload),
    Metrics(MetricsPayload),
    NetworkState(NetworkStatePayload),
    CommandResult(CommandResultPayload),
    WatchdogEvent(WatchdogEventPayload),
    UpdateResult(UpdateResultPayload),
    Heartbeat,
}

/// Messages from server to agent
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "payload")]
#[serde(rename_all = "snake_case")]
pub enum ServerMessage {
    AuthAck(AuthAckPayload),
    Command(CommandPayload),
    ConfigUpdate(serde_json::Value),
    Update(UpdatePayload),
    Ack { message_id: Option<String> },
    Error { code: String, message: String },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthPayload {
    pub api_key: String,
    /// Hardware-derived device ID (for site-based registration)
    #[serde(default)]
    pub device_id: Option<String>,
    pub hostname: String,
    pub os_type: String,
    pub os_version: String,
    pub agent_version: String,
    /// Architecture (amd64, arm64, etc.)
    #[serde(default = "default_arch")]
    pub architecture: String,
    /// Previous version if reconnecting after update
    #[serde(default)]
    pub previous_version: Option<String>,
    /// Update ID if reconnecting after update
    #[serde(default)]
    pub pending_update_id: Option<Uuid>,
}

fn default_arch() -> String {
    "amd64".to_string()
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthAckPayload {
    pub success: bool,
    pub agent_id: Option<Uuid>,
    pub error: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsPayload {
    pub timestamp: chrono::DateTime<chrono::Utc>,
    pub cpu_percent: f32,
    pub memory_percent: f32,
    pub memory_used_bytes: u64,
    pub memory_total_bytes: u64,
    pub disk_percent: f32,
    pub disk_used_bytes: u64,
    pub disk_total_bytes: u64,
    pub network_rx_bytes: u64,
    pub network_tx_bytes: u64,
    pub os_type: String,
    pub os_version: String,


Now let me check some of the other migrations to understand the complete schema: