How TinyBus Modules Are Loaded and Verified in OpenHuman

OpenHuman loads TinyBus modules through a seven-stage pipeline that validates SHA-256 digests, verifies ABI contract versions, and initializes isolated in-process brokers before exposing module capabilities to the core system.

The tinyhumansai/openhuman repository implements a secure plugin architecture using the TinyBus framework to extend core functionality without recompiling the main binary. Understanding how TinyBus modules are loaded and verified in OpenHuman is essential for developers building third-party integrations or auditing the system's supply-chain security. The loading pipeline enforces strict cryptographic and ABI compatibility checks through a static registry compiled directly into the binary.

The Module Loading Pipeline

OpenHuman follows a deterministic sequence to ensure only approved, unmodified code executes within the core process.

Step 1 – Module Registry Lookup

The process begins with a static registry defined in src/openhuman/modules/registry.rs. This file contains the MODULE_REGISTRY table, which lists every approved module along with its release tag, artifact URL, and expected SHA-256 digest. Because this registry is compiled into the binary, the set of loadable modules is fixed at build time, preventing unauthorized library loading at runtime.

Step 2 – Artifact Download

When the core requests a module (e.g., "tinydocs"), the system retrieves the corresponding entry from MODULE_REGISTRY and downloads the artifact from the specified release URL. The artifact is a cdylib (C-compatible dynamic library) compiled against the TinyBus ABI standard. The file is staged locally before any verification occurs.

Step 3 – SHA-256 Digest Verification

After the download completes, OpenHuman computes a SHA-256 hash of the downloaded file and compares it against the digest stored in the registry entry. A mismatch triggers an immediate abort, preventing tampered or corrupted binaries from proceeding. This step protects against supply-chain attacks and ensures bit-for-bit reproducibility of deployed modules.

Step 4 – ABI Compatibility Check

TinyBus modules expose a known interface symbol (tinybus::Interface) and a contract version. The loader uses libloading to retrieve the TINYBUS_INTERFACE symbol from the shared library and invokes check_contract_version() to validate compatibility against CURRENT_TINYBUS_CONTRACT_VERSION compiled into the core. This guards against crashes caused by mismatched Rust toolchains or breaking changes in the TinyBus protocol.

Step 5 – Broker Initialization

Once cryptographic and ABI checks pass, the core creates a dedicated message broker via tinybus::OnceBus::init_in_process(). This broker owns a private message bus for that specific module instance, providing the communication fabric for RPC endpoints, service registration, and event publication. The module receives this broker handle during initialization.

Step 6 – Isolation Guarantees

Although modules run in-process, OpenHuman enforces isolation through TinyBus’s deadline-driven queues and panic-catching middleware. A misbehaving module cannot corrupt the host process memory; failures are contained within the module’s broker boundary and propagate as controlled errors back to the core. This architecture provides the performance of native plugins with the safety boundaries typically associated with out-of-process services.

Step 7 – Runtime Integration

With the broker established, the core registers the module’s RPC controllers, tool schemas, and domain-specific event handlers through the internal operations layer. From the user’s perspective, the module’s capabilities appear as native OpenHuman features (e.g., document generation, wallet handling, or channel providers), fully integrated into the system’s feature set.

Implementation Example

The following Rust code demonstrates the complete loading sequence as implemented in src/openhuman/modules/registry.rs:

use openhuman::modules::registry::MODULE_REGISTRY;

// Request a module by its identifier (e.g. "tinydocs")
let entry = MODULE_REGISTRY.get("tinydocs").expect("module not registered");

// 1. Download the artifact
let artifact_path = download_module(entry.url).await?;

// 2. Verify the SHA-256 digest
verify_digest(&artifact_path, &entry.sha256)?;

// 3. Load the shared library
let lib = unsafe { libloading::Library::new(&artifact_path)? };

// 4. Perform TinyBus ABI check
let iface: tinybus::Interface = unsafe { lib.get(b"TINYBUS_INTERFACE")? };
iface.check_contract_version(CURRENT_TINYBUS_CONTRACT_VERSION)?;

// 5. Initialise the broker for the module
let broker = tinybus::OnceBus::init_in_process(lib)?;

Once loaded, interacting with the module’s capabilities follows standard RPC patterns:

// After the module is loaded, its RPC namespace becomes available
let result = core_rpc_client
    .call("tinydocs_generate_document", json!({ "input": "Hello world" }))
    .await?;
println!("Generated document ID: {}", result["document_id"]);

Key Source Files and Architecture

The verification pipeline spans several critical components within the tinyhumansai/openhuman codebase:

  • src/openhuman/modules/registry.rs: Contains the static MODULE_REGISTRY table and the entry point for the loading sequence. This file defines the ground truth for approved module versions and their cryptographic digests.

  • src/openhuman/modules/loader.rs: Implements the runtime logic coordinating download, verification, and dynamic library initialization using the libloading crate.

  • src/openhuman/modules/bus.rs: Wraps TinyBus primitives to provide per-module OnceBus instances, managing message routing and panic isolation.

  • src/openhuman/modules/ops.rs: Handles registration of RPC controllers, tool schemas, and event subscribers after successful module initialization.

Summary

  • Static Registry: The MODULE_REGISTRY in src/openhuman/modules/registry.rs hardcodes allowed modules, ensuring only pre-approved code can be fetched.
  • Cryptographic Verification: SHA-256 digests validate artifact integrity before library loading occurs.
  • ABI Safety: Contract version checks prevent runtime crashes from incompatible Rust compiler versions or breaking API changes.
  • In-Process Isolation: OnceBus brokers provide fault containment without the overhead of inter-process communication.
  • Zero-Downtime Extensibility: New capabilities deploy as separate modules without rebuilding the core OpenHuman binary.

Frequently Asked Questions

How does OpenHuman prevent tampered TinyBus modules from executing?

OpenHuman computes a SHA-256 hash of the downloaded module artifact and compares it against the digest stored in the compiled MODULE_REGISTRY. Any mismatch aborts the loading process immediately, ensuring only the exact binaries authorized by the maintainers can execute.

What happens if a TinyBus module was compiled with a different Rust version?

The loader performs an ABI compatibility check by calling check_contract_version() on the tinybus::Interface symbol retrieved from the library. If the module’s contract version does not match CURRENT_TINYBUS_CONTRACT_VERSION compiled into the core, the load fails with an ABI mismatch error.

Are TinyBus modules sandboxed in separate processes?

No, modules run in-process for performance, but they are isolated through TinyBus’s architecture. Each module receives its own OnceBus broker with deadline-driven queues and panic-catching layers, ensuring that failures remain contained within the module’s boundary without crashing the host core.

Where is the list of approved modules defined?

The approved module list, including release URLs and SHA-256 digests, is defined as a static table in src/openhuman/modules/registry.rs. This registry is compiled directly into the OpenHuman binary, making the set of loadable modules immutable at runtime.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →