mirror of
https://github.com/ruvnet/RuView.git
synced 2026-10-18 21:00:22 -05:00
@ruvnet/ruview 0.7.0 gives CLI, MCP, and SDK access to RuView sensing hardware on the machine it is attached to, and to other machines over SSH. Devices (ADR-373, src/devices/): - ruview_devices_scan: pyserial port list classified by USB VID:PID (Espressif native USB, CP210x, CH34x, FTDI) into ESP32 / mmWave / RPLIDAR roles with the command that confirms each. - ruview_esp32_capture: receive-only UDP listener parsing ADR-018 CSI frames, vitals, and the other 0xC511000x packets per node: rate, sequence loss, RSSI, subcarriers, frequency, device vitals. - ruview_mmwave_read: MR60BHA2 (60 GHz) and LD2410 (24 GHz) parsers ported byte-for-byte from firmware mmwave_sensor.c; baud/frame auto-detect. - ruview_lidar_read: RPLIDAR SCAN over serial (start/stop, DTR best-effort) and the iPhone LiDAR relay as a WebSocket client (token only via RUVIEW_LIDAR_TOKEN; statistics only, never raw depth). - Dependency-free serial via a fixed pyserial pump (argv-only, bounded, hex output immune to secret redaction). Schema-level port pattern validation added to the policy validator. - All device tools require the new `device-access` MCP grant. Remote hosts (ADR-374, src/remote.js): - ~/.config/ruview/hosts.json (0600), CLI-only `hosts add`; strict name/target validation against ssh option and shell injection. - `ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -- <target>` running a version-pinned `ruview call <tool> --read-only`, every token single-quoted; read-only enforced locally and remotely; no mutations, credentialed reads, or host hopping. MCP needs `remote-host` plus the remote tool's grant. Also: device-access skill, doctor `devices`/`remote` groups, SDK `devices.*`/`hosts.*` with types, generic `ruview call` verb, guidance capability, 320 KiB package budget, CI smoke expects 22 tools. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_015H55jmprfz4oHWXSFbX5rf
3.2 KiB
3.2 KiB
ADR-374: Remote host access over SSH (read-only)
- Status: proposed
- Date: 2026-09-30
- Deciders: RuView maintainers; acceptance pending
- Tags: remote, ssh, hardware, least-authority, mcp
- Related: ADR-369, ADR-373
Context
RuView hardware usually hangs off a different machine from the one the operator or agent works on: a Raspberry Pi next to the ESP32s, a NUC running the sensing server, a Cognitum Seed. Cloud agent sessions cannot reach local USB at all.
"Host access" should not mean opening a new network service with its own credentials: that adds attack surface and secret handling. Operators already have SSH.
Decision
- Where work runs.
- Hardware tools always execute on the machine the hardware is attached to.
- Interactive work runs in a local Claude Code session on that machine. It
can be driven from the Claude app through Remote Control
(
claude remote-controlin the repo). - Other machines are reached over SSH.
- Hosts registry.
- Stored in
~/.config/ruview/hosts.json(directory 0700, file 0600). - Written only by the CLI:
ruview hosts add --name --ssh [--port] [--version]. MCP can list hosts but never add them. - Names must match
^[a-z0-9][a-z0-9-]{0,31}$. Targets must be[user@]hostname: no options, spaces, shell metacharacters or leading dash.
- Stored in
- Transport.
- Local ssh arguments:
ssh -o BatchMode=yes -o ConnectTimeout=10 -o StrictHostKeyChecking=yes -T [-p N] -- <target> <command>. - No password prompts, and no trust-on-first-use from the tool. The operator pins the host key once interactively.
- The remote command is
npx -y @ruvnet/ruview@<exact version> call <tool> --read-only --args-json <json>, with every token single-quoted for the remote POSIX shell.
- Local ssh arguments:
- Read-only, twice.
- Locally,
ruview_host_runaccepts only tools that are read-only, use no credentials, and are notruview_host_*(no host hopping). It validates arguments against the tool schema before sending. - Remotely,
call --read-onlyrepeats the check and schema validation. - Flash, train, calibrate and Cognitum Spaces reads are never forwarded.
- Locally,
- Grants. Over MCP,
ruview_host_runneedsremote-hostplus the remote tool's own grant (for exampledevice-access). - Failures are classified with remedies:
host_key_unverified,ssh_auth_failed,host_unreachable,remote_node_missing,unknown_host,remote_tool_not_allowed.
Evidence
Tests in harness/ruview/test/remote.test.mjs cover:
- host-entry injection cases (
-oProxyCommand=…,;, spaces,$(…), backticks); - quoting, verified by running the quoted command through a real
sh; - the refusal list;
- grant composition;
- the file mode;
call --read-onlyrefusingruview_node_flashthrough the real CLI.
No SSH server was available in the development container, so a live round-trip to a real host is still to be done.
Consequences
- Remote hosts get the same tools with no new daemon, port or credential store.
- The remote needs Node 20+ and npm registry access (or a pre-installed
version), and
sshmust be on the local PATH.doctor --group remotechecks the local side. - Remote mutations stay manual by design.