# SPEC-007: Managed-Agent Installer Builder ("Build Installer") **Status:** Proposed **Priority:** P2 **Requested By:** Mike (2026-05-30) **Estimated Effort:** Medium ## Overview Add a dashboard **"Build Installer"** wizard that produces a pre-labeled managed/persistent (unattended) agent installer — the ScreenConnect "Build Installer" flow. The operator picks a naming strategy and fills Company, Site, Department, Device Type, and Tag, chooses the platform/type, and gets the installer via **Download**, **Copy URL**, or **Send Link**. Once installed, the agent enrolls and appears in the machines list already carrying those labels (so SPEC-003 inventory / SPEC-005 rows / SPEC-006 search are populated at install time, not only agent-detected). Success = a tech can build and hand off a labeled permanent-agent installer entirely from the console, no CLI or manual query-string crafting. **Reference (screenshot 2026-05-30):** modal "Build Installer" with fields **Name** (Use Machine Name / custom), **Company**, **Site**, **Department**, **Device Type**, **Tag**, **Type** (Windows .exe), and share actions **Send Link · Copy URL · Download**. ## What already exists (and what's missing) The embed-config build path is **already implemented**: `server/src/api/downloads.rs` appends an `EmbeddedConfig` (magic marker `GURUCONFIG` + length + JSON) to the base `static/downloads/guruconnect.exe`; `AgentDownloadParams` already accepts `company`, `site`, `tags`, `api_key`; the agent reads it back at `agent/src/config.rs:223` (`read_embedded_config`). The downloads routes are public links (`main.rs:425`). Missing for the ScreenConnect-parity builder: - **No dashboard UI** to drive it (endpoints exist, no wizard). - **Department + Device Type** are not in `EmbeddedConfig` (downloads.rs:21 / config.rs:20), not in `AgentStatus`, not persisted on `connect_machines`. - **Name strategy** ("Use Machine Name" vs. custom) isn't modeled. - **Share actions** beyond Download: **Copy URL** and **Send Link** don't exist. - **Key selection** — which agent key the installer embeds (shared `AGENT_API_KEY` vs. a per-machine/site key) isn't surfaced. ## Scope ### Included in v1 - **Dashboard "Build Installer" modal** (triggered from the Machines page, e.g. a `Build +` action): fields Name (Use Machine Name | custom), Company, Site, Department, Device Type, Tag(s), Type (platform); validates and calls the build endpoint. - **Extend `EmbeddedConfig`** (`downloads.rs` + `agent/src/config.rs`) and `AgentDownloadParams` with `department` and `device_type`; agent maps them through to `AgentStatus` (proto) so they persist on `connect_machines` (SPEC-003 columns) the same way `organization`/`site`/`tags` do today. - **Name strategy:** `Use Machine Name` (agent uses live hostname — current default) or a custom override embedded in the config (`hostname_override` already exists, `config.rs:63`). - **Share actions:** **Download** (exists), **Copy URL** (returns the parameterized public download URL for clipboard), **Send Link** (email the download URL — see deps). - **Type/platform selector:** Windows (.exe) in v1, with the dropdown structured to add macOS/Linux later (those agents are roadmap P3 — show only available types). - **Key selection:** embed the correct agent key for enrollment — default the shared/site key; ready to use a per-machine key when that lands (SPEC-004/roadmap). ### Explicitly out of scope - Attended **support-code** session creation — that's a different flow (support codes already exist); this builder is for **managed/persistent** agents only. - macOS/Linux installer artifacts — UI is forward-compatible but only Windows .exe ships. - MSI/MSP packaging, GPO/Intune deployment bundles — `.exe` only in v1. - Code-signing changes — the base binary signing is SPEC-001/ADR-002; the builder just appends config to the already-signed base (note: appending after signing invalidates the Authenticode signature — see Open Questions). ## Architecture - **Dashboard (`dashboard/src/features/machines/`):** new `BuildInstallerModal.tsx` + `dashboard/src/api/installer.ts`; opens from the Machines page. Builds the request, shows Download/Copy URL/Send Link. Admin-only. - **Relay-server (`server/src/api/downloads.rs`):** extend `EmbeddedConfig` + `AgentDownloadParams` with `department`, `device_type`, and a `name`/`hostname_override` field; the existing append-config build path is reused. Add a small endpoint to return the **built URL** (for Copy URL) and a **Send Link** action (POST that emails the URL). - **Agent (`agent/src/config.rs`):** add `department`, `device_type` to `EmbeddedConfig` and `Config`; thread into `send_status` (`agent/src/session/mod.rs:236`) on `AgentStatus`. - **Protobuf (`proto/guruconnect.proto`):** add `department` and `device_type` to `AgentStatus` (or to SPEC-003's `DeviceInventory`) so the relay can persist them. Pick one home and keep it consistent with SPEC-003. - **DB:** `connect_machines.department` / `device_type` columns come from SPEC-003; no new migration here if SPEC-003 lands first (else add them). ## Implementation details - Files to touch: `server/src/api/downloads.rs:21,40` (EmbeddedConfig + AgentDownloadParams: `department`, `device_type`, `name`/override); `server/src/main.rs` (Copy-URL / Send-Link routes if added; existing download routes reused); `agent/src/config.rs:20,59` (Config + EmbeddedConfig fields); `agent/src/session/mod.rs:236` (`AgentStatus` population); `proto/guruconnect.proto` (AgentStatus/DeviceInventory fields); `dashboard/src/features/machines/BuildInstallerModal.tsx` (new), `dashboard/src/api/installer.ts` (new). - The build URL is the existing public download endpoint with query params (`company`, `site`, `tags`, `department`, `device_type`, `name`, key) — Copy URL just returns that string; Download streams the appended binary; Send Link emails it. ## Security considerations - **Embedded key exposure.** The installer embeds an agent enrollment key in a public, user-shareable artifact/URL. Prefer a **per-machine or per-site key** over the shared `AGENT_API_KEY` so a leaked installer can be revoked without re-keying the fleet; at minimum make the embedded key revocable. This is the strongest reason to pair with per-machine agent keys (SPEC-004 Security / roadmap). - **Build endpoint auth.** Building/Copy-URL/Send-Link must be **admin-authenticated** (`AuthenticatedUser`) even though the resulting *download* link is public; do not let an unauthenticated caller mint installers with arbitrary embedded keys. - **Input validation.** Company/Site/Department/Device Type/Tag/Name are embedded as JSON and later shown in the console and reported on `AgentStatus` — length-cap and sanitize (no injection into the embedded JSON, no oversized config blob; the agent already length-checks the embedded blob, `config.rs:230`). - **Send Link.** Validate the recipient; rate-limit; the email contains a key-bearing URL, so treat it as a credential delivery (audit who built/sent what). - **Signature note.** Appending config after Authenticode signing breaks the signature (Open Questions) — a security/UX consideration for SmartScreen, not just cosmetic. ## Testing strategy - **Unit:** `EmbeddedConfig` round-trips `department`/`device_type` (write → append → `read_embedded_config` → equal); URL builder encodes all fields + key correctly. - **Integration:** build an installer with all fields set → download → embedded config parses → (simulated) agent registers and `connect_machines` shows the embedded company/ site/department/device_type/tags. Copy URL returns a URL that downloads the same. Build endpoints reject unauthenticated callers. - **Manual:** from the console, build a labeled installer, install on a test box, confirm it appears in Access pre-labeled; verify Copy URL and (if shipped) Send Link. ## Effort estimate & dependencies - **Size: Medium.** The build/append path exists; bulk of the work is the dashboard wizard, the `department`/`device_type` plumbing (agent + proto + config), and Send-Link email. - **Depends on:** **SPEC-003** for the `department`/`device_type` persistence columns (and it feeds SPEC-003/005/006 by populating those fields at install time). **Pairs with** per-machine agent keys (SPEC-004/roadmap) for a revocable embedded key. **Send Link** needs an outbound email/SMTP capability the server may not have yet — gate that sub-feature on it (Copy URL + Download have no such dep). - **Unblocks:** self-service managed-agent onboarding from the console; pre-labeled fleet data feeding inventory, list view, and search. ## Open questions 1. **Authenticode signature vs. appended config.** Appending the config blob after the base `.exe` is signed invalidates the signature (SmartScreen warnings). Options: sign *after* config injection per-build (needs signing in the build path — heavier, ties to ADR-002/SPEC-001), embed config in a signature-preserving way (e.g. a signed wrapper / resource section), or accept unsigned per-build installers. Decide in planning — this is the biggest design question. 2. **Embedded key model** — shared `AGENT_API_KEY`, per-site key, or per-machine key minted at build time? Strongly prefer revocable per-site/per-machine. 3. **Send Link transport** — does the server have/want SMTP? If not, ship Download + Copy URL in v1 and defer Send Link (or use a `mailto:` prefilled link as a stopgap). 4. **Name strategy storage** — custom name via existing `hostname_override` (`config.rs:63`) vs. a separate display-name field that doesn't change the reported hostname. Which does the console treat as authoritative? 5. **Platform dropdown** — hide unavailable platforms, or show disabled "coming soon" entries for macOS/Linux?