# Privacy Mode Enforcement in OpenHuman's Rust Core: A Layered Security Model

> OpenHuman's Rust core enforces privacy mode by routing network requests through a centralized egress enforcer. Discover how it blocks outbound traffic without restarts.

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

---

**OpenHuman's Rust core prevents data leaks by routing every network request through a centralized egress enforcer that reads a globally locked `LivePolicy`, allowing the system to block outbound traffic in `LocalOnly` mode without restarting the process.**

The `tinyhumansai/openhuman` repository implements privacy mode enforcement as a first-class security primitive inside its Rust core. Rather than scattering checks across individual tools, the architecture unifies configuration, live-policy management, and egress control into a cohesive pipeline. The following sections break down exactly how the core stores the mode, updates it at runtime, and blocks unauthorized network traffic.

## Configuration and RPC Layer

The privacy mode originates in the core configuration schema and remains accessible through stable RPC endpoints.

### PrivacyMode Schema Definition

The enum and its defaults live in [`src/openhuman/config/schema/privacy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/privacy.rs). This file establishes the valid privacy states—such as `Standard` and `LocalOnly`—that the rest of the system consumes.

### Runtime Configuration via RPC

External clients read or mutate the mode through the controllers defined in [`src/openhuman/config/schemas/controllers.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schemas/controllers.rs) (lines 428-433). The endpoints `openhuman.config_get_privacy_mode` and `openhuman.config_set_privacy_mode` provide the primary interface for runtime inspection and adjustment.

## Live-Policy Layer for Runtime Privacy Mode Enforcement

Between persistent configuration and network enforcement sits the `LivePolicy`, a globally accessible structure that maintains the mutable authority on privacy mode.

### Global LivePolicy with RwLock

When the core boots, it creates a `LivePolicy` that wraps a mutable `RwLock<PrivacyMode>` ([`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs), lines 31-35 and 50-52). The initial value is seeded from the installed `SecurityPolicy` field `policy.privacy_mode`, managed in [`src/openhuman/security/policy/enforcement.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/enforcement.rs) through `SecurityPolicy::with_privacy_mode` and its accessor. Any subsystem can query the active value by calling `current_privacy_mode()`, which is implemented at lines 156-163 in the live-policy module.

### Thread-Local Overrides for Testing

The core supports temporary, thread-local overrides through `test_privacy_scope()` ([`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs), lines 111-115). This function returns an RAII guard that forces a specific mode for the current thread only, enabling tests or short-lived operations to run under a restricted stance without altering the global `LivePolicy`.

### Hot-Reloading Privacy Mode Without Restart

Administrators can change the privacy mode at runtime via `reload_privacy(new_mode)` ([`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs), lines 270-306). The implementation clones the current policy, swaps only the `privacy_mode` field, and atomically re-installs the policy object. Because all readers call `current_privacy_mode()`, they immediately observe the updated value without requiring a process restart.

## Egress Enforcement Layer

Every network-bound operation in the core must pass through a centralized enforcement routine that consults the live policy before transmitting data.

### The enforce_egress Entry Point

The canonical check lives in [`src/openhuman/security/egress/enforce.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/egress/enforce.rs). The function `enforce_egress` begins by capturing the live value with `let mode = current_privacy_mode();` (lines 155-166). When the mode is `Standard`, the operation proceeds and the core emits a debug log formatted as `[privacy][egress-enforce] ... — permitted`. When the mode is `LocalOnly`, the request is rejected and logged as `[privacy][egress-enforce] ... — denied` (lines 166-193).

### Network Tool Integration

All outbound tools invoke this enforcer prior to opening sockets. The modules [`src/openhuman/tools/impl/network/http_request.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/network/http_request.rs), [`src/openhuman/tools/impl/network/curl.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/network/curl.rs), and [`src/openhuman/tools/impl/network/web_fetch.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/network/web_fetch.rs) contain inline guards such as:

```rust
if current_privacy_mode() == PrivacyMode::LocalOnly {
    // block outbound request
}

```

These files also carry comments referencing privacy epic identifiers (for example, "privacy epic S7, #4441"), linking the enforcement logic back to the original design requirements.

## Subsystem Propagation

To guarantee consistency, every major subsystem receives the config-derived mode during startup and forwards it into the live-policy. In [`src/openhuman/channels/runtime/startup.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/runtime/startup.rs) (line 288), the Channels runtime invokes `.with_privacy_mode(config.privacy.mode)` so that the voice pipeline, TUI, and other components inherit the same privacy stance from the moment they initialize.

## Code Examples

The following snippets demonstrate how to query, update, and observe privacy mode enforcement in practice.

Query the current privacy mode over RPC:

```rust
let privacy = core_rpc_client
    .invoke("openhuman.config_get_privacy_mode", json!({}))
    .await?;
println!("Current mode: {}", privacy["mode"]); // e.g. "Standard"

```

Switch to `LocalOnly` mode over RPC:

```rust
core_rpc_client
    .invoke("openhuman.config_set_privacy_mode", json!({ "mode": "local_only" }))
    .await?;

```

Execute a network request that respects the enforced mode:

```rust
let result = tools::network::http_request::execute(
    "GET",
    "https://api.example.com/data",
    /* body */ None,
).await;
// In LocalOnly mode the request is blocked and returns an error.

```

## Summary

- **Configuration storage**: [`src/openhuman/config/schema/privacy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/privacy.rs) defines the `PrivacyMode` enum, while [`src/openhuman/config/schemas/controllers.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schemas/controllers.rs) exposes RPC endpoints for live updates.
- **Live-policy authority**: [`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs) maintains a global `RwLock<PrivacyMode>` that is queried through `current_privacy_mode()` and updated atomically via `reload_privacy(new_mode)`.
- **Centralized egress checks**: [`src/openhuman/security/egress/enforce.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/egress/enforce.rs) implements `enforce_egress`, which permits or denies every outbound request based on the live policy.
- **Tool-level compliance**: Network tools in [`src/openhuman/tools/impl/network/http_request.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/network/http_request.rs), [`curl.rs`](https://github.com/tinyhumansai/openhuman/blob/main/curl.rs), and [`web_fetch.rs`](https://github.com/tinyhumansai/openhuman/blob/main/web_fetch.rs) all defer to the central enforcer before transmitting data.
- **Subsystem-wide consistency**: Startup routines such as [`src/openhuman/channels/runtime/startup.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/runtime/startup.rs) propagate the config mode into the live-policy so the entire process shares one authoritative state.

## Frequently Asked Questions

### What is privacy mode enforcement in OpenHuman?

Privacy mode enforcement is the Rust core mechanism that inspects every network-bound operation against a centrally managed `PrivacyMode` value. When set to `LocalOnly`, the core blocks all outbound traffic so that user data remains on the device.

### How does the Rust core block network requests in LocalOnly mode?

The core blocks requests through the `enforce_egress` function in [`src/openhuman/security/egress/enforce.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/egress/enforce.rs). This function calls `current_privacy_mode()` and, if the result is `LocalOnly`, logs a denial and prevents the operation from proceeding. Every network tool—including HTTP, curl, and web fetch implementations—invokes this check before opening a connection.

### Can privacy mode be changed without restarting the OpenHuman core?

Yes. Administrators can call `openhuman.config_set_privacy_mode` over RPC, which triggers `reload_privacy(new_mode)` in [`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs) (lines 270-306). The function clones the active policy, updates the `privacy_mode` field, and re-installs it atomically, so all subsequent checks use the new value immediately.

### How do tests override privacy mode without affecting global state?

Tests use the `test_privacy_scope()` helper from [`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs) (lines 111-115). This helper creates a thread-local RAII guard that temporarily forces a specific `PrivacyMode` for the current thread only, leaving the global `LivePolicy` unchanged.