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

116 lines
8.1 KiB
Markdown

# 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:76``GET /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.rs``create_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.rs``create_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.proto``SessionRequest` `:8`, `StartStream` `:261`, `AgentStatus` `:271`,
`AdminCommand` `:286`. **Add** `ConsentRequest` / `ConsentResponse` messages.
- `agent/src/session/mod.rs``SessionState` `:71`, persistent-vs-support logic. **Change** to
register against a broker-assigned `agent_id` (= GuruRMM `device_id`).
- `agent/src/transport/websocket.rs``connect()` `: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.rs``register_protocol_handler()` `:131` (`guruconnect://<session>?token=&server=`).
Reused for native-viewer launch URLs the broker returns.
### GuruRMM (RMM)
- `server/src/api/commands.rs:87-157``POST /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.rs``run_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-310``commandsApi` 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-573``execute_command()` `:971``run_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`
(`useMutation``commandsApi.send``useQuery` poll). The Remote Control button mirrors this.
- **Per-agent credential issuance (RMM):** `server/src/api/enroll.rs:38-139``generate_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_keys``id`, `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.