Files
guru-connect/specs/native-remote-control/references.md
Mike Swanson e3e95f8fa7
Some checks failed
Build and Test / Build Server (Linux) (push) Has been cancelled
Build and Test / Build Agent (Windows) (push) Has been cancelled
Build and Test / Security Audit (push) Has been cancelled
Build and Test / Build Summary (push) Has been cancelled
Run Tests / Test Server (push) Has been cancelled
Run Tests / Test Agent (push) Has been cancelled
Run Tests / Code Coverage (push) Has been cancelled
Run Tests / Lint and Format Check (push) Has been cancelled
chore: sync repository to current working state
Brings azcomputerguru/guru-connect up to the authoritative working copy that
had been maintained in the claudetools monorepo: Phase 1 security and
infrastructure (middleware, metrics, utils, token blacklist, deployment
scripts, security audits) plus the native-remote-control integration spec.
Preserves the repo .gitignore, .cargo, and server/static/downloads.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 06:15:29 -07:00

8.1 KiB

Native Remote Control — Code References

Two repos. GC = guru-connect (D:\claudetools\projects\msp-tools\guru-connect, lives in the claudetools repo). RMM = GuruRMM (projects/msp-tools/guru-rmm, a git submodule tracking azcomputerguru/gururmm). Paths below are relative to each repo root.

Files that will be touched

guru-connect (GC)

  • server/src/main.rs — route table; create_code :382, list_sessions :425, get_session :433, list_machines :467, /health :254, public /api/version :300. Add the /api/integration/v1/ namespace: GET .../capabilities, POST .../sessions, POST .../sessions/:id/viewer-token, POST .../agents/:agent_id/keys; register the server-to-server integration auth layer. Model the (unauthenticated) capabilities endpoint on the existing /api/version route.
  • CONTRACT.md (new — GC repo root or docs/) — the semver'd integration contract doc both teams keep front of mind. Source of truth for the surface; tested in CI (Task 11).
  • server/src/api/releases.rs:76GET /api/version handler (no auth, for agent polling). Pattern to model GET /api/integration/v1/capabilities on.
  • server/static/viewer.html — the existing web viewer; gets an ?embed=1 mode (hide standalone chrome, accept host-provided session/token, emit postMessage lifecycle events for the RMM host).
  • server/src/middleware/security_headers.rs:30 (frame-ancestors 'none') and :37-39 (X-Frame-Options) — the embedding blocker. Add a per-route scoped allowlist for the viewer path only (RMM origin from env); leave every other route at 'none'.
  • server/src/session/mod.rs — in-memory SessionManager; register_agent() :95, join_session() :254. Change to allow a session to be pre-created/keyed by agent_id before the agent connects, then bound when the agent registers.
  • server/src/db/sessions.rscreate_session() :22. Change/add to persist pre-created sessions and a is_managed/source marker; reconcile in-memory state on startup.
  • server/src/db/support_codes.rscreate_support_code() :24, get_support_code() :43. Reused as-is for the attended path (broker calls POST /api/codes).
  • server/src/relay/mod.rs — agent WS handler :55/:236; validate_agent_api_key() :187 (currently JWT-or-shared-AGENT_API_KEY, comment at :200 flags DB keys as future). Change to validate against the new per-machine key table.
  • server/src/auth/jwt.rs — JWT signing/validation. Add a short-lived, session-scoped viewer token mint.
  • server/migrations/add connect_agent_keys (per-machine keys) and session columns; follow the existing 001_initial_schema.sql / 003_auto_update.sql style. Idempotent (IF NOT EXISTS).
  • proto/guruconnect.protoSessionRequest :8, StartStream :261, AgentStatus :271, AdminCommand :286. Add ConsentRequest / ConsentResponse messages.
  • agent/src/session/mod.rsSessionState :71, persistent-vs-support logic. Change to register against a broker-assigned agent_id (= GuruRMM device_id).
  • agent/src/transport/websocket.rsconnect() :32 (builds ?agent_id=&api_key=&support_code=). Pass the per-machine key.
  • agent/src/tray/mod.rs + a new consent dialog — add the attended-mode consent prompt (handle ConsentRequest).
  • agent/src/install.rsregister_protocol_handler() :131 (guruconnect://<session>?token=&server=). Reused for native-viewer launch URLs the broker returns.

GuruRMM (RMM)

  • server/src/api/commands.rs:87-157POST /api/agents/{agent_id}/command dispatch (online → WS ServerMessage::Command; offline → queued). Reuse to push the "ensure + launch guru-connect" instruction to the endpoint agent.
  • server/src/api/mod.rs:162 — route registration site. Add the new broker route.
  • server/src/api/add remote_control.rs: POST /api/agents/:agent_id/remote-control (body selects unattended|attended); talks to the GC server API, returns a viewer launch URL.
  • server/src/db/ + server/migrations/add a remote_control_sessions record (or reuse tech_sessions from 010_tunnel_sessions.sql) for audit (agent_id, tech_id, connect_session_id, mode, timestamps).
  • agent/src/transport/websocket.rsrun_command() :1050, execute_command() :971. Add a RemoteControl/launch path (or a dedicated command_type) that, on Windows, ensures the guru-connect agent binary is present (download + SHA-256 verify) and launches it in the requested mode passing device_id as the GC agent_id.
  • agent/src/device_id.rs:1-99 — source of the stable cross-product identity. Read-only.
  • dashboard/src/pages/AgentDetail.tsx:1893-1931 — tab/header + action-button area. Add the "Remote Control" button (open viewer URL on success).
  • dashboard/src/components/CommandTerminal.tsx:60-106 — the canonical button→api.post()useQuery action pattern to copy.
  • dashboard/src/api/client.ts:293-310commandsApi pattern. Add remoteControlApi.start(agentId, mode).

Similar existing implementations (patterns to follow)

  • Per-agent action dispatch (RMM): server/src/api/commands.rs:87-157 + agent reception agent/src/transport/websocket.rs:570-573execute_command() :971run_command() :1050. The broker's "launch guru-connect" instruction follows this exact send-command path.
  • Dashboard action button → poll (RMM): dashboard/src/components/CommandTerminal.tsx:82-105 (useMutationcommandsApi.senduseQuery poll). The Remote Control button mirrors this.
  • Per-agent credential issuance (RMM): server/src/api/enroll.rs:38-139generate_api_key("agk_") :103, hash_api_key() :104, plaintext returned once :138. Model connect_agent_keys provisioning on this.
  • Support-code minting (GC): server/src/main.rs:382 create_code + server/src/db/support_codes.rs:24. The attended path reuses this directly.
  • Agent WS auth handshake (RMM): agent/src/transport/websocket.rs:100-197 — how api_key/device_id are presented; the per-machine GC key provisioning should align with this lifecycle.
  • Half-built generic tunnel (RMM), for reference only: server server/src/api/tunnel.rs:1-232 (routes NOT registered), server/src/db/tunnel.rs:1-152, server/migrations/010_tunnel_sessions.sql, agent agent/src/tunnel/mod.rs:62-197, WS msgs server/src/ws/mod.rs:287-300. The tech_sessions/tunnel_audit schema is a usable model for the remote-control audit record.

Database schema

guru-connect (existing — server/migrations/)

  • connect_machines (001_initial_schema.sql:8) — agent_id UNIQUE, hostname, is_persistent, status, plus agent_version/organization/site/tags from 003_auto_update.sql.
  • connect_sessions (001_initial_schema.sql:27) — id, machine_id, is_support_session, support_code, status. Add is_managed / source marker for broker-initiated sessions.
  • connect_support_codes (001_initial_schema.sql:59) — reused unchanged for attended.
  • connect_session_events (001_initial_schema.sql:43) — audit; emit broker/consent events here.
  • releases (003_auto_update.sql:9) — has checksum_sha256; reuse for the verify-before-launch supply-chain guard.
  • New: connect_agent_keysid, agent_id FK, key_hash, created_at, revoked_at. Idempotent migration, hashed keys only (mirror RMM enroll pattern).

GuruRMM (existing — server/migrations/)

  • Agent identity: agent_id (UUID, assigned at WS auth), device_id (agent/src/device_id.rs), site_id, per-agent agk_ key (hashed) from server/src/api/enroll.rs.
  • tech_sessions / tunnel_audit (010_tunnel_sessions.sql) — model for the new remote_control_sessions audit table (or extend tech_sessions with a mode).

Migration discipline for both Rust servers: idempotent IF NOT EXISTS, let the server binary apply migrations on startup, cargo sqlx prepare if any query!() macro changes. See gururmm/sqlx-migrations standard.