Trust boundaries
The hosted RC service authenticates users, coordinates workspaces, relays live connections, and stores control-plane metadata. The Node is the final execution verifier for locked machines.
The browser application is part of the trusted client computing base because RC serves its JavaScript. A fully compromised web server could replace that JavaScript when an authorized user visits and ask the browser-held control key to sign operations. RC Lock prevents the server/database from creating those signatures by itself; the standalone CLI avoids this web-code-delivery dependency.
RC does not claim that browser control is resistant to a malicious server actively serving modified client code.
Browser and CLI encrypted control
Each live browser or CLI control session creates a fresh client X25519 key pair. The Node has a pinned static X25519 transport key and creates a fresh X25519 key pair for the session.
- The client and Node derive one X25519 secret using the Node static transport key.
- They derive a second X25519 secret using the fresh Node ephemeral key.
- The two secrets are concatenated and passed through HKDF-SHA256.
- The derivation is salted with the session challenge and bound to the device ID and client ID.
- The result is an AES-256-GCM key used for process control traffic.
The Node signs the handshake with its Ed25519 device identity. The signature binds the challenge, device, client, client ephemeral key, Node static transport key, Node ephemeral key, and session ID.
Frames use direction-specific nonces and authenticated additional data containing the session ID, sequence number, and direction. Sequence numbers must increase by exactly one. A gap or replay closes the session.
A later compromise of only the Node's long-term X25519 transport key is not enough to decrypt a recorded session because the fresh Node ephemeral private key is not retained.
Control transport
Authenticated HTTP endpoints carry browser/CLI control-session setup and non-trickle WebRTC signaling. Browser live metadata and lifecycle events use cookie-authenticated Server-Sent Events. Encrypted browser/CLI control frames are carried only by a reliable ordered WebRTC DataChannel.
The managed service uses Cloudflare STUN for ICE discovery and asks Cloudflare TURN for short-lived ICE credentials from the RC backend when configured. The long-lived TURN token ID/API token remain server-side; browser and Node receive only the temporary ICE username/credential. ICE prefers direct connectivity and uses TURN relay candidates when necessary. RC does not relay browser/CLI control frames through HTTP, SSE, or WebSocket.
WebRTC adds DTLS transport encryption, but RC currently retains its own AES-256-GCM control framing inside the DataChannel. Transport diagnostics are kept only as bounded in-memory operational state rather than durable audit history. Changing or removing the inner encryption is a separate security change.
RC Lock
RC Lock is the authority snapshot stored locally on each Node. It contains workspace members and roles, passkey credential public keys, authorized API signing public keys with scopes and expiry, and hashes of active execution-capable MCP grants.
The first lock is a trust-on-first-use bootstrap from the RC instance used during enrollment. It never overwrites an existing lock.
Every later authority change must reference the Node's current lock hash and generation and be signed by a passkey-backed control identity belonging to a user who is already an Owner in the current snapshot.
The Node rejects stale transitions, invalid signatures, expired API/MCP credentials, and credentials missing from the local snapshot. Accepting a new lock generation invalidates live encrypted control sessions so they reconnect against current authority.
Node authentication
Node HTTP and WebSocket authentication uses the Node's Ed25519 identity. RC issues a short-lived one-time challenge; the Node signs the challenge together with the request method and path.
Consumed challenges cannot be reused. Current Nodes also reject legacy plaintext browser/CLI process, update, and remove commands.
Process data
SQLite stores lifecycle metadata only: process ID, device, origin, PTY flag, state, attribution, timestamps, exit code, signal, and bounded error text.
Browser and CLI command, working directory, terminal geometry, stdin, stdout, stderr, and scrollback are not persisted in process history. Live PTY scrollback is bounded in RC Node memory for reattach while the process is alive. Browser/CLI terminal bytes travel only over WebRTC, either directly or through TURN, and are never relayed by the RC application WebSocket.
MCP Terminal
Standard remote MCP does not participate in RC's browser/CLI end-to-end transport. For mcp:terminal, command and output plaintext pass through RC server memory while the MCP call is active.
That memory is bounded to 256 KiB per active process buffer. Completed buffers expire after five minutes; inactive running buffers expire after thirty minutes. MCP command/output is not written to SQLite process history.
A compromised RC server with an active Terminal grant could issue commands allowed by that grant until the grant expires or is revoked.
SSH gateway
RC runs stock OpenSSH sshd at the gateway. Clients normally reach it through rc ssh-proxy over the public HTTPS/WebSocket endpoint; Nodes keep only their outbound RC connection and do not expose SSH.
Password and keyboard-interactive authentication are disabled. A registered SSH public key is bound to a passkey-backed RC control identity, and the forced bridge routes by the immutable RC device ID. The Node independently verifies that control grant and requires the user to be an Operator or Owner before starting a process.
SSH terminates at the RC gateway, so commands, terminal bytes, file contents, and rsync traffic are plaintext in gateway memory while active. A compromised gateway with an active SSH authorization could act as that user. This is a deliberate trust model difference from browser/CLI end-to-end control.
Node release integrity
GitHub Releases are the native RC release trust boundary. rc upgrade verifies the selected RC, kernel, and core-component artifact digests, validates the downloaded executables and component graph, and refuses native downgrades.
Managed WebAssembly components update independently through rc update; a component-only update does not replace the native RC binary or kernel.