Compare commits

...

2 Commits

Author SHA1 Message Date
9af59158b2 Add team feedback to requirements document
- 25 detailed requirements from Howard's team
- Backstage mode (like RustDesk unattended access)
- Toolbox features (TaskMgr, CMD, PowerShell, RegEdit)
- Annotations, chat, and security requirements
- Cross-platform and mobile support needs
- PSA integrations (Halo, Autotask, ConnectWise)
- Branding and white-label requirements
- Session recording and reporting features

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 13:52:05 -07:00
e118fe6698 Add agent_id to WebSocket authentication
- Add UUID-based agent_id field to Config struct
- Auto-generate and persist agent_id on first run
- Include agent_id in WebSocket query parameters
- Update production server URL to connect.azcomputerguru.com

Fixes WebSocket connection failure where server expected agent_id parameter.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 13:52:05 -07:00
4 changed files with 145 additions and 10 deletions

View File

@@ -690,3 +690,112 @@ When a machine is selected, show comprehensive info in side panel:
- Single binary server (Docker or native)
- Single binary agent (MSI installer + standalone EXE)
- Cloud-hostable or on-premises
---
## Team Feedback (2025-12-28)
### Howard's Requirements
#### Core Remote Support & Access Capabilities
1. **Screen Sharing & Remote Control**
- View and interact with the end-user's desktop in real time
- Technicians can control mouse and keyboard, just like sitting at the remote machine
2. **Attended & Unattended Access**
- Attended support: on-demand support sessions where the user connects via a session code or link
- Unattended access: persistent remote connections that allow access anytime without user presence
3. **Session Management**
- Initiate, pause, transfer, and end remote sessions
- Session transfer: pass control of a session to another technician
- Session pause and idle timeout controls
4. **File & Clipboard Sharing**
- Drag-and-drop file transfer between local and remote systems
- Clipboard sharing for copy/paste between devices
5. **Multi-Session Handling**
- Technicians can manage multiple concurrent remote sessions
6. **Multi-Monitor Support**
- Seamlessly switch between multiple monitors on the remote system
#### Advanced Support & Administrative Functions
7. **Backstage / Silent Support Mode**
- Execute tasks, run scripts, and troubleshoot without disrupting the user's screen (background session)
8. **Shared & Personal Toolboxes**
- Save commonly used tools, scripts, or executables
- Share them with team members for reuse in sessions
9. **Custom Scripts & Automation**
- Automate repetitive tasks during remote sessions
10. **Diagnostic & Command Tools**
- Run PowerShell, Command Prompt, view system event logs, uninstall apps, start/stop services, kill processes, etc.
- Better PowerShell/CMD running abilities with configurable timeouts (checkboxes/text boxes instead of typing every time)
#### Security & Access Control Features
11. **Encryption**
- All traffic is secured with AES-256 encryption
12. **Role-Based Permissions**
- Create granular technician roles and permissions to control who can do what
13. **Two-Factor & Login Security**
- Support for multi-factor authentication (MFA) and other secure login methodologies
14. **Session Consent & Alerts**
- Require end-user consent before connecting (configurable)
- Alerts notify users of maintenance or work in progress
15. **Audit Logs & Session Recording**
- Automatically record sessions
- Maintain detailed logs of connections and actions for compliance
#### Communication & Collaboration Tools
16. **Real-Time Chat**
- Text chat between technician and end user during sessions
17. **Screen Annotations**
- Draw and highlight areas on the user's screen for clearer instructions
#### Cross-Platform & Mobile Support
18. **Cross-Platform Support**
- Remote control across Windows, macOS, Linux, iOS, and Android
19. **Mobile Technician Support**
- Technicians can support clients from mobile devices (view screens, send Ctrl-Alt-Delete, reboot)
20. **Guest Mobile Support**
- Remote assistance for user Android and iOS devices
#### Integration & Customization
21. **PSA & Ticketing Integrations**
- Launch support sessions from RMM/PSA and other ticketing systems
22. **Custom Branding & Interface**
- White-labeling, logos, colors, and custom client titles
23. **Machine Organization & Search**
- Dynamic grouping of devices and custom property filtering to locate machines quickly
#### Reporting & Monitoring
24. **Session & System Reports**
- Audit logs, session histories, technician performance data, etc.
25. **Diagnostic Reporting**
- Collect performance and diagnostic information during or after sessions
### Additional Notes from Howard
- **64-bit client requirement** - ScreenConnect doesn't have a 64-bit client, which limits deployment options
- **PowerShell timeout controls** - Should have UI controls (checkboxes/text boxes) for timeouts rather than typing commands every time

View File

@@ -3,6 +3,7 @@
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use uuid::Uuid;
/// Agent configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -13,6 +14,10 @@ pub struct Config {
/// Agent API key for authentication
pub api_key: String,
/// Unique agent identifier (generated on first run)
#[serde(default = "generate_agent_id")]
pub agent_id: String,
/// Optional hostname override
pub hostname_override: Option<String>,
@@ -25,6 +30,10 @@ pub struct Config {
pub encoding: EncodingConfig,
}
fn generate_agent_id() -> String {
Uuid::new_v4().to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CaptureConfig {
/// Target frames per second (1-60)
@@ -101,9 +110,15 @@ impl Config {
let contents = std::fs::read_to_string(&config_path)
.with_context(|| format!("Failed to read config from {:?}", config_path))?;
let config: Config = toml::from_str(&contents)
let mut config: Config = toml::from_str(&contents)
.with_context(|| "Failed to parse config file")?;
// Ensure agent_id is set and saved
if config.agent_id.is_empty() {
config.agent_id = generate_agent_id();
let _ = config.save();
}
return Ok(config);
}
@@ -114,13 +129,22 @@ impl Config {
let api_key = std::env::var("GURUCONNECT_API_KEY")
.unwrap_or_else(|_| "dev-key".to_string());
Ok(Config {
let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
.unwrap_or_else(|_| generate_agent_id());
let config = Config {
server_url,
api_key,
agent_id,
hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
capture: CaptureConfig::default(),
encoding: EncodingConfig::default(),
})
};
// Save config with generated agent_id for persistence
let _ = config.save();
Ok(config)
}
/// Get the configuration file path
@@ -182,6 +206,7 @@ pub fn example_config() -> &'static str {
# Server connection
server_url = "wss://connect.example.com/ws"
api_key = "your-agent-api-key"
agent_id = "auto-generated-uuid"
# Optional: override hostname
# hostname_override = "custom-hostname"

View File

@@ -48,6 +48,7 @@ impl SessionManager {
let transport = WebSocketTransport::connect(
&self.config.server_url,
&self.config.agent_id,
&self.config.api_key,
).await?;

View File

@@ -29,17 +29,17 @@ pub struct WebSocketTransport {
impl WebSocketTransport {
/// Connect to the server
pub async fn connect(url: &str, api_key: &str) -> Result<Self> {
// Append API key as query parameter
let url_with_auth = if url.contains('?') {
format!("{}&api_key={}", url, api_key)
pub async fn connect(url: &str, agent_id: &str, api_key: &str) -> Result<Self> {
// Append agent_id and API key as query parameters
let url_with_params = if url.contains('?') {
format!("{}&agent_id={}&api_key={}", url, agent_id, api_key)
} else {
format!("{}?api_key={}", url, api_key)
format!("{}?agent_id={}&api_key={}", url, agent_id, api_key)
};
tracing::info!("Connecting to {}", url);
tracing::info!("Connecting to {} as agent {}", url, agent_id);
let (ws_stream, response) = connect_async(&url_with_auth)
let (ws_stream, response) = connect_async(&url_with_params)
.await
.context("Failed to connect to WebSocket server")?;