# How the OpenHuman Module Registry Validates and Loads TinyBus CDylib Modules Using SHA-256 Verification

> Learn how the OpenHuman module registry validates and loads TinyBus cdylibs using SHA-256 verification. Ensure secure and attested module loading for your projects.

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

---

**The OpenHuman module registry uses a compiled-in whitelist of `ModuleRecord` entries combined with runtime SHA-256 digest verification to ensure only cryptographically attested TinyBus native modules (cdylib) are downloaded, extracted, and dynamically loaded.**

The `tinyhumansai/openhuman` repository implements a secure native module system where every loadable TinyBus dynamic library is catalogued in a static registry. This architecture prevents runtime injection of unauthorized code by enforcing cryptographic verification at multiple stages before `dlopen` ever executes.

## The Compiled-In Registry Architecture

OpenHuman maintains its security boundary through a **compiled-in registry** defined in [`src/openhuman/modules/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/registry.rs). Unlike dynamic module marketplaces that accept runtime registrations, this static table prevents attackers from introducing arbitrary loadable modules after compilation.

Each entry is a `ModuleRecord` structure defined in [`src/openhuman/modules/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/types.rs). These records encapsulate the module's identity, versioning, and platform-specific assets. The registry serves as the single source of truth for:

- **Module IDs** and **bus names** (e.g., `tinydocs`, `tinywallet`)
- **Object paths** mapped to bus names (converting `.` to `/`)
- **Release URLs** pointing to GitHub release tags
- **Platform assets** containing expected SHA-256 digests
- **Load policies** determining initialization timing

The registry initialization includes comments (lines 3-10 in [`registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/registry.rs)) explicitly documenting why the whitelist is compiled rather than configurable: to eliminate attack vectors where malicious actors might append unauthorized entries at runtime.

## SHA-256 Verification Flow

When a session requests a native capability, the TinyBus loader executes a four-stage validation pipeline. The OpenHuman registry provides the ground-truth digests that TinyBus uses to verify downloaded artifacts.

### Fetching the Release Checksum

The loader first queries the `release_url` specified in the `ModuleRecord` (e.g., `https://github.com/tinyhumansai/tinydocs/releases/tag/v0.1.14`). It downloads the [`checksum.toml`](https://github.com/tinyhumansai/openhuman/blob/main/checksum.toml) file associated with the release, which contains metadata for all distributed archives.

### Platform Asset Selection

Not every release artifact runs on every host. The `candidates_for` function in [`src/openhuman/modules/platform.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/platform.rs) generates a prioritized list of **host keys** based on the current operating system, architecture, and glibc version (e.g., `linux-x86_64`).

The loader selects the `PlatformAsset` from the `ModuleRecord` whose host key matches the current environment. This selection determines which archive name and SHA-256 digest will be used for verification.

### Cryptographic Digest Verification

Before extraction begins, TinyBus computes the SHA-256 hash of the downloaded archive in its entirety. It compares this computed digest against the lower-case 64-character hexadecimal string stored in the `sha256` field of the selected `PlatformAsset`.

If the digests differ by even a single bit, the loading process aborts immediately. This verification occurs **before** any `dlopen` call, ensuring that corrupted or tampered binaries never execute in-process.

### Runtime Loading and dlopen

Upon successful hash validation, the archive extracts to a temporary location. The loader then performs `dlopen` on the resulting `.so`, `.dylib`, or `.dll` file. Following successful load, OpenHuman validates that the module's bus name correctly maps to its advertised object path through the conversion logic tested in `every_object_path_matches_its_bus_name` (lines 87-95 in [`registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/registry.rs)).

## Load Policies and Module Lifecycle

The registry distinguishes between two initialization strategies via the `LoadPolicy` enum:

- **`LoadPolicy::Eager`** — Modules like `tinymemory` load at startup because their absence would alter the core RPC surface available to clients.
- **`LoadPolicy::Lazy`** — Modules such as `tinydocs`, `tinywallet`, and `tinyjuice` remain dormant until a session explicitly requests their capability, conserving memory and reducing attack surface during idle periods.

This policy is encoded in the `ModuleRecord` and enforced by the session manager when initializing the TinyBus runtime.

## Registry Validation and Security Invariants

The [`registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/registry.rs) file contains comprehensive unit tests (lines 74-124) that enforce data integrity at compile time. These tests verify:

- **Uniqueness constraints** — No duplicate module IDs or bus names exist.
- **Path consistency** — Every object path correctly derives from its bus name.
- **Digest format** — All SHA-256 strings are exactly 64 lower-case hexadecimal characters.
- **Archive naming** — Asset filenames encode their host key and semantic version.
- **URL integrity** — Release URLs point to GitHub tags matching the recorded version string.

These invariants ensure that the compiled-in whitelist contains only well-formed, internally consistent records before the binary ships.

## Implementation Example

The following Rust code demonstrates how consumer code interacts with the registry and verification pipeline:

```rust
// 1. Locate a module record by its ID (e.g., "tinydocs")
use openhuman::modules::registry::{find, ALL};

let record = find("tinydocs")
    .expect("module ID not known");

// 2. Choose the correct asset for the current platform
use openhuman::modules::platform::candidates_for;
let host_keys = candidates_for("linux", "x86_64", Some((2, 39)));
let asset = record.asset_for(&host_keys[0])
    .expect("no asset for this host");

// 3. Verify the SHA-256 digest (TinyBus does this internally)
//    Here we show the expected digest for reference:
println!("Expected SHA-256: {}", asset.sha256);

// 4. Load the module (TinyBus provides the loader)
use openhuman::modules::loader::load_module;
let module = load_module(record).expect("failed to load module");

// 5. Use the module via TinyBus (example: call a TinyBus method)
let result = module.call("SomeMethod", args);

```

Note that while OpenHuman supplies the static `ModuleRecord` and host-key selection logic in `src/openhuman/modules/`, the actual download, SHA-256 verification, and `dlopen` operations are performed by the TinyBus runtime (`tinybus::load::load_module`).

## Summary

- The **compiled-in registry** at [`src/openhuman/modules/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/registry.rs) acts as a whitelist preventing runtime injection of unauthorized modules.
- Each `ModuleRecord` contains **platform-specific assets** with expected SHA-256 digests stored in lower-case hexadecimal format.
- The **verification flow** fetches [`checksum.toml`](https://github.com/tinyhumansai/openhuman/blob/main/checksum.toml), matches host keys via `candidates_for`, compares cryptographic digests, and only then proceeds to `dlopen`.
- **Load policies** (`Lazy` vs `Eager`) control whether modules initialize at startup or on-demand.
- **Unit tests** enforce uniqueness, path consistency, and digest format invariants before compilation.

## Frequently Asked Questions

### How does OpenHuman prevent loading of modified or malicious TinyBus modules?

OpenHuman prevents tampering through **SHA-256 attestation** stored in `PlatformAsset` records. Before `dlopen` executes, TinyBus downloads the module archive and computes its SHA-256 hash. The loader aborts if the computed digest does not match the 64-character hexadecimal string defined in [`src/openhuman/modules/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/registry.rs). This ensures only cryptographically identical binaries to those published in the GitHub release execute.

### What happens if a requested module is not in the compiled-in registry?

If `find()` in [`src/openhuman/modules/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/registry.rs) returns `None` for a requested module ID, the loading process fails immediately. Because the registry is compiled into the binary and cannot be modified at runtime, there is no mechanism to load "unlisted" modules, effectively preventing dynamic code injection attacks.

### How does the registry handle different operating systems and architectures?

The `candidates_for` function in [`src/openhuman/modules/platform.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/platform.rs) generates **host keys** representing the current OS/architecture tuple (e.g., `linux-x86_64`). Each `ModuleRecord` contains multiple `PlatformAsset` entries for different host keys. The loader selects the asset matching the current environment, ensuring the correct `.so`, `.dylib`, or `.dll` variant loads with its corresponding SHA-256 digest.

### What is the difference between Lazy and Eager load policies?

**Eager** modules (such as `tinymemory`) initialize during OpenHuman startup because their absence would change the available RPC methods. **Lazy** modules (including `tinydocs` and `tinywallet`) defer download and `dlopen` until a session explicitly requests their capability, reducing resource consumption and attack surface during periods when those features remain unused.