Watch
1
0
Fork
You've already forked RedFlag
0
RedFlag/RAF/components/05-desktop.md
Fimeg d9ba008f67 raf: sync docs to code + relative cross-reference links
Handler/migration counts, calculateBackoff -> calculateDelay, machine-id
binding (cross-platform machineid + fallbacks, not hostname), last-reviewed
dates, and made [[cross-references]] relative so they resolve.
2026-06-15 09:39:34 -04:00

4.1 KiB

Desktop Component

A credential-less tray window onto the local agent — it can see, it can ask, it cannot mutate.


Doctrine

The desktop app (desktop/, Tauri 2) holds no tokens, reads no protected config, and never talks to the fleet server. Its entire world is the agent's local API socket, and its authorization is its operating-system identity: the user running it is either in the redflag-local group or the kernel refuses the connection. See security/01-trust-boundaries, Local Trust Boundary.

The credential-less surface is a design decision, not an inevitability — the reasoning lives in security/06-standalone-authority: group membership only gates the request; the judgment stays in the gates and the root-owned mint key, and same-host token schemes don't reproduce an off-host boundary. The decision is held open in one respect: the socket does not capture peer identity (SO_PEERCRED), so on a multi-user host an approval journals as an event, not as a person. Whether that needs per-user attribution (peer creds, or a polkit prompt) is an open call, not settled doctrine.

Fleet-server context, when it comes, joins this same app rather than spawning a second local-only application.


Structure

desktop/
├── src/main.rs           # Tauri shell: tray, window, localapi client, health reporter
├── tauri.conf.json       # Window config, dev/build frontend wiring
└── icons/icon.png        # 8-bit RGBA — tray icon constructor rejects 16-bit PNGs

web/
├── index.desktop.html    # Desktop entry (separate from the fleet SPA's index.html)
├── src/desktop/          # LocalAgentApp — status dashboard, no auth surface
└── vite.desktop.config.ts# Builds to dist-desktop/, emits the entry as index.html

One Rust binary, one React entry. The frontend is embedded at build time (frontendDist: ../web/dist-desktop); release builds are self-contained — no dev server, no localhost dependency. Dev builds (cargo build without tauri build) compile in the Vite devUrl and require npm run dev:desktop running.

The fleet SPA and the desktop entry share the web/ tree but are distinct applications: the desktop entry never renders the sign-in screen because it has nothing to sign in to.


Agent IPC

The Rust shell speaks plain HTTP/1.1 over the local socket (/var/lib/redflag/agent/localapi/redflag-agent.sock; named pipe \\.\pipe\RedFlagAgentLocal on Windows). The frontend reaches it only through Tauri invoke commands — the webview itself has no socket access.

  • local_statusGET /v1/identity + GET /v1/status — the dashboard snapshot, polled every 5s.
  • Health reporter thread → POST /v1/desktop every 30s with version, uptime, and window state. This is how the agent (and through it, the fleet) knows a tray is alive on the host.

On EACCES the shell diagnoses rather than reports: it distinguishes "user not in redflag-local" (gives the usermod command) from "membership added but the login session predates it" (tells the user to re-log) by comparing /etc/group against the process's live groups. Group membership is stamped at login; this is the component's most common support question, so the error message carries the answer.


Lifecycle

Installed and provisioned by the agent install script (binary, autostart entry, group enrollment — linux.sh.tmpl step 7c). Updated through the capability gate like every other binary: desktop-self tokens, hash-verified and atomically swapped by the helper (components/04-helper). Server-side minting and pre-tray host healing are in progress — docs/tasks/UPDATE-002. The component is not yet in release version lockstep; closing that is docs/tasks/INSTALL-001.


Cross-References


Last reviewed: 2026-06-14