# How the Experimental iOS Client Connects to the Desktop Core with TunnelTransport in OpenHuman

> Learn how the experimental OpenHuman iOS client connects to the desktop core via TunnelTransport. Discover XChaCha20-Poly1305 encrypted TCP tunnels for secure JSON-RPC communication.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: deep-dive
- Published: 2026-08-24

---

**The experimental OpenHuman iOS client connects to the desktop core using `TunnelTransport`, which implements an XChaCha20‑Poly1305 encrypted tunnel over TCP to secure JSON‑RPC communication between the mobile client and the localhost core server.**

The OpenHuman repository contains an experimental iOS client that requires secure communication with the desktop‑bundled core process. The project achieves this through a pluggable transport layer that supports multiple strategies, with **TunnelTransport** providing the cryptographic guarantees necessary for safe RPC transmission over local network interfaces.

## Core Server Architecture

When the OpenHuman desktop application launches, it initializes the core process to expose a JSON‑RPC interface that the experimental iOS client can consume.

### Process Initialization and Token Generation

The core launches in‑process via `CoreProcessHandle` defined in [`app/src-tauri/src/core_process.rs`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/src/core_process.rs). This Rust module opens an HTTP RPC listener on a random localhost port and generates a unique bearer token stored as `core_rpc_token`. Frontend clients, including the iOS transport layer, retrieve this token through the Tauri command exposed in [`app/src-tauri/src/core_rpc_token.rs`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/src/core_rpc_token.rs), ensuring that only authorized local clients can authenticate subsequent RPC requests.

### ConnectionProfile Transport Selection

The transport abstraction lives in [`app/src/services/transport/index.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/services/transport/index.ts), which exports the `ConnectionProfile` class. This profile acts as a factory that instantiates one of three transport implementations based on the deployment scenario:

- **`LanHttpTransport`** – Plain HTTP over the local area network without encryption, suitable only for trusted networks.
- **`CloudHttpTransport`** – Connects to a remote cloud endpoint for internet‑based synchronization.
- **`TunnelTransport`** – The encrypted strategy used by the iOS client to protect data in transit.

## TunnelTransport Implementation Details

The `TunnelTransport` class resides in [`app/src/services/transport/tunnel_transport.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/services/transport/tunnel_transport.ts) and provides the cryptographic layer that shields JSON‑RPC traffic from network observers.

### Encryption Handshake and Key Derivation

When instantiated, the transport performs the following operations:

1. **TCP Socket Creation** – Opens a raw TCP socket (or WebSocket wrapper) to `127.0.0.1` on the port advertised by the desktop core.
2. **Symmetric Key Generation** – Generates a random 32‑byte key using a secure random number generator.
3. **Cipher Initialization** – Constructs an `XChaCha20Poly1305` instance from the `@stablelib/xchacha20poly1305` library, providing authenticated encryption with associated data (AEAD).

### Request Encryption and Authentication

Every RPC request follows this encryption workflow:

- The plaintext JSON‑RPC body is sealed using `XChaCha20Poly1305.seal()`, which generates a 24‑byte nonce prepended to the ciphertext.
- The bearer token obtained from `core_rpc_token` is included as an `Authorization: Bearer <token>` header **inside** the encrypted envelope, ensuring that authentication credentials remain confidential.
- The combined nonce and ciphertext payload transmits over the TCP socket to the core.

On receiving a response, the transport extracts the response nonce, decrypts the payload using `XChaCha20Poly1305.open()`, and returns the decrypted JSON to the caller.

## iOS Client Integration

The experimental iOS codebase instantiates the secure transport in [`app/src/ios/transport.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/ios/transport.ts):

```typescript
import { ConnectionProfile } from '../services/transport';
import { TunnelTransport } from '../services/transport/tunnel_transport';

export const iosCore = new ConnectionProfile({
  transport: new TunnelTransport(),
});

// Example RPC invocation from iOS UI layer
export async function fetchUserInfo() {
  const response = await iosCore.request({
    method: 'GET',
    path: '/auth/me',
    headers: {},
  });
  return JSON.parse(new TextDecoder().decode(response.body));
}

```

The `iosCore` object exposes a `request` method that iOS UI layers call to execute domain‑specific OpenHuman RPC endpoints such as `GET /rpc` or `POST /rpc`, with all underlying encryption handled transparently by the `TunnelTransport` instance.

## End‑to‑End Data Flow

The complete communication path between the experimental iOS client and the desktop core follows this sequence:

1. **iOS Client** calls `ConnectionProfile.request()` with an unencrypted JSON‑RPC payload.
2. **`TunnelTransport.encrypt()`** generates a random 24‑byte nonce, seals the payload (including the Authorization header), and transmits the combined nonce+ciphertext over the TCP socket.
3. **Desktop Core** receives the raw bytes on the port managed by `CoreProcessHandle`, decrypts the envelope using the shared cipher context, and forwards the plaintext to the RPC handler.
4. **Core Response** travels back through the same encrypted tunnel, where `TunnelTransport.decrypt()` recovers the JSON payload before returning it to the iOS UI.

This flow ensures that the underlying TCP traffic remains opaque to any network interceptor, providing confidentiality and integrity for all RPC exchanges.

## Implementation Code Examples

### Client‑Side TunnelTransport Class

```typescript
// app/src/services/transport/tunnel_transport.ts
import { XChaCha20Poly1305 } from '@stablelib/xchacha20poly1305';
import { randomBytes } from '@stablelib/random';

export class TunnelTransport {
  private socket: WebSocket;
  private cipher: XChaCha20Poly1305;

  constructor(corePort: number) {
    const key = randomBytes(32);
    this.cipher = new XChaCha20Poly1305(key);
    this.socket = new WebSocket(`ws://127.0.0.1:${corePort}`);
  }

  async request(payload: Uint8Array): Promise<Uint8Array> {
    // Encrypt with unique nonce per request
    const nonce = randomBytes(24);
    const encrypted = this.cipher.seal(nonce, payload);
    
    // Transmit nonce + ciphertext
    this.socket.send(this.concat(nonce, encrypted));
    
    // Await and decrypt response
    const raw = await this.waitMessage();
    const respNonce = raw.subarray(0, 24);
    const respCipher = raw.subarray(24);
    return this.cipher.open(respNonce, respCipher);
  }

  private concat(a: Uint8Array, b: Uint8Array): Uint8Array {
    const result = new Uint8Array(a.length + b.length);
    result.set(a);
    result.set(b, a.length);
    return result;
  }

  private waitMessage(): Promise<Uint8Array> {
    return new Promise((resolve) => {
      this.socket.onmessage = (event) => {
        resolve(new Uint8Array(event.data));
      };
    });
  }
}

```

### Core‑Side RPC Handler

The Rust core does not require tunnel‑specific logic; it processes decrypted JSON‑RPC requests in [`src/openhuman/core/rpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/core/rpc.rs):

```rust
pub async fn handle_http_rpc(req: Request<Body>) -> Result<Response<Body>, RpcError> {
    // Body arrives decrypted from the client side
    let json_payload = parse_json_body(req).await?;
    process_json_rpc(json_payload).await
}

```

## Key Files and Components

- **[`app/src/services/transport/tunnel_transport.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/services/transport/tunnel_transport.ts)** – Implements the XChaCha20‑Poly1305 encryption layer, manages the TCP/WebSocket tunnel, and exposes the `request` method consumed by iOS.
- **[`app/src/services/transport/index.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/services/transport/index.ts)** – Defines the `ConnectionProfile` abstraction that selects between LAN, Cloud, and Tunnel transport strategies.
- **[`app/src/ios/transport.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/ios/transport.ts)** – Entry point for the experimental iOS client that instantiates `ConnectionProfile` with `TunnelTransport`.
- **[`app/src-tauri/src/core_process.rs`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/src/core_process.rs)** – Launches the embedded core process, binds the RPC listener to a random localhost port, and generates the bearer token.
- **[`app/src-tauri/src/core_rpc_token.rs`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/src/core_rpc_token.rs)** – Exposes the `core_rpc_token` to authorized frontend clients via Tauri commands.
- **[`src/openhuman/core/rpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/core/rpc.rs)** – Rust RPC handler that processes decrypted JSON‑RPC requests as standard HTTP traffic.

## Summary

- The experimental iOS client uses **`TunnelTransport`** to establish an encrypted communication channel with the OpenHuman desktop core.
- **XChaCha20‑Poly1305** provides authenticated encryption for all RPC payloads, with unique nonces generated per request.
- The bearer token authenticating the client travels inside the encrypted envelope, protecting credentials from network eavesdropping.
- The architecture maps encrypted TCP traffic to the standard JSON‑RPC interface exposed by `CoreProcessHandle`, requiring no changes to the core's request handling logic.

## Frequently Asked Questions

### What encryption standard does TunnelTransport use?

`TunnelTransport` uses **XChaCha20‑Poly1305**, an authenticated encryption with associated data (AEAD) cipher. The implementation leverages the `@stablelib/xchacha20poly1305` library to generate 24‑byte nonces and 32‑byte symmetric keys for each tunnel session, ensuring both confidentiality and integrity of JSON‑RPC traffic.

### How does the iOS client authenticate with the desktop core?

The iOS client retrieves a bearer token via the Tauri command `core_rpc_token` exposed in [`app/src-tauri/src/core_rpc_token.rs`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/src/core_rpc_token.rs). This token is embedded as an `Authorization: Bearer <token>` header **inside** the encrypted payload before transmission. Because the encryption occurs before the data leaves the client, the authentication credentials remain protected from any intermediary network observer.

### Can TunnelTransport connect over Wi‑Fi or is it restricted to localhost?

While the current implementation targets **localhost TCP connections** (typically `127.0.0.1` on the random port assigned by `CoreProcessHandle`), the transport layer itself is protocol‑agnostic. The encrypted tunnel could theoretically traverse any TCP‑capable network path, though the experimental iOS client in the OpenHuman repository is designed specifically for local device‑to‑desktop pairing over shared network interfaces or USB forwarding.

### Why use TunnelTransport instead of standard HTTPS?

`TunnelTransport` specifically solves the **local trust boundary** problem for an experimental iOS client that cannot easily validate self‑signed certificates or trust store configurations required for local HTTPS. By using a pre‑shared symmetric key derived via the `core_rpc_token` handshake and XChaCha20‑Poly1305 encryption, the system achieves zero‑configuration encrypted communication without the certificate management overhead of TLS, making it ideal for rapid prototyping in the OpenHuman development environment.