# How OpenHuman Enforces Privacy Mode at the Rust Core Level

> Discover how OpenHuman enforces Privacy Mode at the Rust core level by blocking external network calls. Learn about its robust privacy protection.

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

---

**OpenHuman enforces Privacy Mode in its Rust core by intercepting all inference provider instantiation at the dispatcher level, blocking any external network calls when `PrivacyMode::LocalOnly` is active.**

The `tinyhumansai/openhuman` repository implements a zero-trust privacy architecture that prevents data egress through a centralized enforcement point in its Rust core. Understanding how Privacy Mode is enforced at OpenHuman's Rust core level reveals a design that guarantees local-only inference when configured, regardless of which integrations or tools are invoked.

## PrivacyMode Configuration Schema

The privacy contract is defined in [`src/openhuman/config/schema/privacy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/privacy.rs) as a strongly-typed enum that controls data egress permissions across the entire application.

### The Three Privacy Tiers

The `PrivacyMode` enum defines three distinct operational states:

- **LocalOnly** — No data may leave the device. All external model calls to cloud services, managed APIs, or CLI-delegated inference are blocked. Only local runtimes such as Ollama, LM Studio, MLX, or locally hosted OpenAI-compatible servers are permitted.
- **Standard** — The default balanced mode where external models and integrations are allowed as configured. No egress restrictions are applied.
- **Sensitive** — A reserved variant for future privacy slices that will implement redaction, PII detection, and user-approval flows. Currently, this behaves identically to `Standard`.

### Serialization and Defaults

The enum serializes to snake_case strings (`local_only`, `standard`, `sensitive`) to match the repository's TOML configuration conventions. When a `[privacy]` block or `mode` key is missing from the configuration file, Serde's `#[default]` implementation automatically falls back to `PrivacyMode::Standard`, ensuring the application remains functional without explicit user configuration.

## Enforcement at the Inference Dispatcher

The critical enforcement point resides in the inference stack within `src/openhuman/inference/*`, specifically inside the provider resolution logic. Before any network request is issued, the system validates the active privacy mode against the requested provider's locality.

### The resolve_provider Gate

The `resolve_provider` function acts as the single gatekeeper for all inference operations. According to the OpenHuman source code, the logic validates provider locality before instantiation:

```rust
use crate::openhuman::config::PrivacyMode;
use crate::openhuman::config::Config;

/// Resolve an inference provider. Returns an error when the
/// privacy mode forbids external calls.
pub fn resolve_provider(config: &Config) -> Result<Box<dyn Provider>, ProviderError> {
    match config.privacy.mode {
        PrivacyMode::LocalOnly => {
            // Only allow providers that run completely locally.
            if provider.is_local() {
                Ok(provider)
            } else {
                Err(ProviderError::PrivacyViolation(
                    "External model calls are blocked by PrivacyMode::LocalOnly".into(),
                ))
            }
        }
        // Standard and Sensitive currently permit any provider.
        PrivacyMode::Standard | PrivacyMode::Sensitive => Ok(provider),
    }
}

```

When `PrivacyMode::LocalOnly` is active, any attempt to instantiate a remote provider—whether OpenAI, Azure, or other hosted inference services—triggers `ProviderError::PrivacyViolation`. This check occurs in the core inference stack, ensuring that **all** code paths capable of causing data egress are guarded by the same privacy-mode gate.

### Error Propagation to the RPC Layer

Violations propagate through the RPC layer with explicit error messaging. When a privacy violation occurs, the system returns a structured error response:

```json
{
  "error": "External model calls are blocked by PrivacyMode::LocalOnly"
}

```

This guarantees that clients receive clear, actionable feedback when privacy settings prevent an operation, rather than opaque connection failures or silent drops.

## Configuring Privacy Mode in Practice

OpenHuman supports both static configuration through files and dynamic updates via RPC, allowing privacy posture adjustments without restarting the core.

### Static Configuration via config.toml

To enforce local-only inference persistently, set the mode in your configuration file:

```toml
[privacy]
mode = "local_only"   # blocks all outbound model calls

```

### Runtime Updates via RPC

Applications can switch modes dynamically using the Core RPC client. The `config_set` method updates the active configuration in [`src/openhuman/config/ops/privacy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/ops/privacy.rs):

```rust
use openhuman_core::api::core::rpc::CoreRpcClient;

// Switch to Standard (default) mode
let _ = client
    .call("config_set", json!({ "privacy": { "mode": "standard" } }))
    .await?;

```

### Handling Privacy Violations in Clients

Client applications should handle `ProviderError::PrivacyViolation` explicitly to guide users:

```typescript
try {
  const result = await coreRpcClient.call("inference_predict", {
    prompt: "Summarize this document",
  });
  console.log(result);
} catch (e) {
  if (e.message.includes("PrivacyMode::LocalOnly")) {
    alert("Your privacy settings prevent remote inference. Switch to Standard mode to use cloud models.");
  } else {
    console.error(e);
  }
}

```

## Architecture and Security Guarantees

Because the privacy check lives in the centralized inference dispatcher—implemented in files such as [`src/openhuman/inference/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/inference/provider.rs)—the privacy posture cannot be bypassed by adding new integrations. Any new provider must be added to the `is_local()` predicate or explicitly allowed by a future privacy slice. This creates a single-source-of-truth privacy gate that consistently prevents user data from leaving the device when `PrivacyMode::LocalOnly` is selected.

The configuration operations in [`src/openhuman/config/ops/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/ops/mod.rs) expose these settings to the frontend and CLI, ensuring changes are persisted in the `Config` struct and immediately respected by the enforcement point.

## Summary

- **PrivacyMode** is defined in [`src/openhuman/config/schema/privacy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/privacy.rs) with variants `LocalOnly`, `Standard`, and `Sensitive`.
- **Enforcement** occurs at the inference dispatcher level via `resolve_provider` before any network request is issued.
- **LocalOnly** mode blocks all non-local providers by checking the `is_local()` predicate and raising `ProviderError::PrivacyViolation` for external services.
- **Configuration** can be set statically in [`config.toml`](https://github.com/tinyhumansai/openhuman/blob/main/config.toml) or updated dynamically via RPC calls to the core.
- **Future-proofing** ensures new integrations cannot bypass privacy controls because all providers must pass through the centralized dispatcher validation.

## Frequently Asked Questions

### What is PrivacyMode::LocalOnly in OpenHuman?

`PrivacyMode::LocalOnly` is a strict operational mode defined in the Rust core that prevents any data from leaving the local device. When active, it blocks all external model calls—including cloud APIs and managed services—and permits only local inference runtimes like Ollama or LM Studio. This mode is enforced at the provider resolution layer before any network connection is attempted.

### How does the Rust core prevent external API calls when Privacy Mode is enabled?

The Rust core prevents external API calls through the `resolve_provider` function in the inference dispatcher. This function checks `config.privacy.mode` before instantiating any provider. If the mode is `LocalOnly` and the provider fails the `is_local()` check, the system immediately returns `ProviderError::PrivacyViolation`, stopping the request before network initialization.

### Can Privacy Mode be bypassed by new integrations or custom tools?

No, Privacy Mode cannot be bypassed by new integrations because the enforcement point is centralized in the core inference stack. Any new provider must pass through the `resolve_provider` gate and implement the `is_local()` predicate. Because this validation occurs in the Rust core rather than individual integration layers, the privacy guarantee holds regardless of which tools or extensions are installed.

### What happens when I try to use a cloud model in LocalOnly mode?

When you attempt to use a cloud model in `LocalOnly` mode, the inference dispatcher detects that the provider is not local and raises `ProviderError::PrivacyViolation`. This error propagates to the RPC layer, returning a JSON error message stating *"External model calls are blocked by PrivacyMode::LocalOnly"*. Client applications receive this explicit error and can prompt the user to switch to `Standard` mode if remote inference is required.