Skip to content

Add trusted external capability provider registry#2548

Open
vaddisrinivas wants to merge 2 commits into
tinyhumansai:mainfrom
vaddisrinivas:codex/oh-2541-external-capability-providers
Open

Add trusted external capability provider registry#2548
vaddisrinivas wants to merge 2 commits into
tinyhumansai:mainfrom
vaddisrinivas:codex/oh-2541-external-capability-providers

Conversation

@vaddisrinivas
Copy link
Copy Markdown
Contributor

@vaddisrinivas vaddisrinivas commented May 23, 2026

Summary

  • Add a generic external capability provider registry for trusted runtime layers.
  • Add config schema support for provider records with trust, enabled state, source URI, and source digest metadata.
  • Expose normalized provider lookup and registration eligibility checks for later admission, policy, and diagnostics code.

Problem

  • OpenHuman has generic policy and generated-tool hooks, but no neutral place to declare which external capability providers are trusted to register capability-backed tools.
  • Without a provider registry, admission and diagnostics code has to duplicate trust metadata or rely on raw strings.

Solution

  • Introduce openhuman::external_capabilities with provider config, normalization, registry construction, and error reporting.
  • Wire external_capability_providers into the top-level config schema with a default-empty configuration.
  • Keep the module generic: it does not load bundles, execute tools, or depend on a provider packaging format.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy: provider normalization, trusted/enabled checks, duplicate records, invalid IDs, and missing names.
  • Diff coverage ≥ 80% — local full coverage not run; focused Rust tests cover the changed module and CI coverage gate will enforce final diff coverage.
  • Coverage matrix updated — N/A: generic config/registry capability, no existing feature row added/removed/renamed.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related: N/A, no coverage-matrix feature ID applies.
  • No new external network dependencies introduced (mock backend used per Testing Strategy): no network dependency added.
  • Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md): N/A, no release-cut UI/runtime smoke surface changed.
  • Linked issue closed via Closes #NNN in the ## Related section.

Impact

  • Runtime/platform impact: new default-empty config and registry API only.
  • Security impact: establishes explicit trust and enablement metadata for external capability providers.
  • Compatibility: existing configs deserialize with defaults.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

Commit & Branch

  • Branch: codex/oh-2541-external-capability-providers
  • Commit SHA: d91b5ef1371e65e81b77ea701e4a6b03e121d6d9

Validation Run

  • pnpm --filter openhuman-app format:check: N/A, Rust-only backend schema/module change.
  • pnpm typecheck: N/A, Rust-only backend schema/module change.
  • Focused tests: cargo test --manifest-path Cargo.toml external_capabilities --lib
  • Rust fmt/check (if changed): cargo fmt --manifest-path Cargo.toml --all --check; git diff --check
  • Tauri fmt/check (if changed): N/A, no Tauri code changed.
  • PR checklist: node scripts/check-pr-checklist.mjs /tmp/openhuman-pr-body-2541.md

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: OpenHuman config can now declare trusted external capability providers.
  • User-visible effect: None by default; registry is empty unless configured.

Parity Contract

  • Legacy behavior preserved: yes, defaults keep existing runtime behavior unchanged.
  • Guard/fallback/dispatch parity checks: invalid or duplicate provider records are reported through registry errors, not silently trusted.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): None found for vaddisrinivas:codex/oh-2541-external-capability-providers.
  • Canonical PR: this PR.
  • Resolution (closed/superseded/updated): N/A.

Summary by CodeRabbit

  • New Features

    • Added a new configuration section to manage external capability providers.
    • Added a provider registry with lookup, listing, validation, normalization, and error reporting.
    • Providers expose a flag determining whether they may register tools.
  • Tests

    • Added unit tests covering id normalization, validation, registry loading, and error cases.
  • Documentation

    • Added module-level documentation for external capability provider APIs.

Review Change Stack

@vaddisrinivas vaddisrinivas requested a review from a team May 23, 2026 15:46
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

📝 Walkthrough

Walkthrough

Adds configurable external capability providers: new config and runtime types, provider ID normalization/validation, a config-backed registry exposing list/get/can_register_tools/errors, unit tests, and integration into the top-level Config and schema re-exports.

Changes

External Capability Provider Registry System

Layer / File(s) Summary
Provider types and defaults
src/openhuman/external_capabilities/types.rs
Adds ExternalCapabilityProviderConfig (serde/schemars), ExternalCapabilityProvidersConfig, runtime ExternalCapabilityProvider, and Default/can_register_tools() implementations.
Registry, normalization, and tests
src/openhuman/external_capabilities/registry.rs
Implements ExternalCapabilityProvider::from_config, normalize_provider_id, and ExternalCapabilityProviderRegistry::from_config that loads providers into a BTreeMap, records errors for invalid/duplicate entries, and exposes is_empty, list, get, can_register_tools, and errors. Includes unit tests for normalization, gating, and error reporting.
Module facade and re-exports
src/openhuman/external_capabilities/mod.rs, src/openhuman/mod.rs
Adds the external_capabilities public module and re-exports normalize_provider_id, ExternalCapabilityProviderRegistry, and provider types.
Schema re-exports and Config integration
src/openhuman/config/schema/tools.rs, src/openhuman/config/schema/types.rs, src/openhuman/config/schema/mod.rs
Re-exports provider config types through the schema tools module, adds external_capability_providers: ExternalCapabilityProvidersConfig to top-level Config with #[serde(default)], initializes it in Config::default(), and reformats the pub use list in schema mod.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 A tiny registry hops in the glade,
IDs trimmed, normalized, and made,
Trusted gates guard every call,
Configured lists stand proud and tall,
Errors logged, and tests parade!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add trusted external capability provider registry' directly and clearly describes the main change: introducing a new registry system for trusted external capability providers.
Linked Issues check ✅ Passed All acceptance criteria from issue #2541 are met: generic provider metadata type [#2541], config-backed registry [#2541], provider id validation/normalization [#2541], lookup/list helpers [#2541], backward compatibility preserved [#2541], and focused tests added [#2541].
Out of Scope Changes check ✅ Passed All changes align with PR objectives: module structure, config schema integration, registry implementation, and tests directly address issue #2541 goals without adding runtime bundle formats, executing external code, or UI components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the working A PR that is being worked on by the team. label May 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/openhuman/external_capabilities/mod.rs (1)

93-111: ⚡ Quick win

Add structured debug/trace logs on registry load error branches

from_config has duplicate/error/state-transition branches but no instrumentation. Add structured debug/trace logs (stable prefix + provider id) for invalid records and duplicates so config diagnosis is grep-friendly.

As per coding guidelines: “Use log / tracing at debug or trace level on RPC entry and exit, error paths, state transitions, and any branch that is hard to infer from tests alone.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/external_capabilities/mod.rs` around lines 93 - 111, The
from_config function currently swallows error and duplicate branches without
instrumentation; update ExternalCapabilityProviders::from_config to emit
structured debug/trace logs: on the Err(err) branch of
ExternalCapabilityProvider::from_config log a trace/debug with a stable prefix
(e.g. "external_capability:invalid") plus the provider config id and the error
string, and on the duplicate branch where providers.contains_key(&provider.id)
is true log a trace/debug with a stable prefix (e.g.
"external_capability:duplicate") plus the conflicting provider.id; use the
project logging crate (log or tracing) consistently and keep messages
machine-grep-friendly and concise to aid config diagnosis.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/external_capabilities/mod.rs`:
- Around line 13-254: The file mixes domain exports, operational logic and tests
— split into focused modules: move the plain data types
(ExternalCapabilityProviderConfig, ExternalCapabilityProvidersConfig,
ExternalCapabilityProvider) into a new types.rs, move the operational code and
registry (ExternalCapabilityProvider::from_config,
ExternalCapabilityProvider::can_register_tools,
ExternalCapabilityProviderRegistry and its impls, normalize_provider_id,
is_separator, trim_optional) into an ops.rs (or registry.rs), and move the
#[cfg(test)] tests into the corresponding sibling (or keep them in
types.rs/ops.rs guarded by cfg(test)); then update mod.rs to only pub mod types;
pub mod ops; and re-export the key symbols (pub use
types::{ExternalCapabilityProviderConfig, ExternalCapabilityProvidersConfig,
ExternalCapabilityProvider}; pub use ops::{ExternalCapabilityProviderRegistry,
normalize_provider_id};) so external callers and tests continue to work.

---

Nitpick comments:
In `@src/openhuman/external_capabilities/mod.rs`:
- Around line 93-111: The from_config function currently swallows error and
duplicate branches without instrumentation; update
ExternalCapabilityProviders::from_config to emit structured debug/trace logs: on
the Err(err) branch of ExternalCapabilityProvider::from_config log a trace/debug
with a stable prefix (e.g. "external_capability:invalid") plus the provider
config id and the error string, and on the duplicate branch where
providers.contains_key(&provider.id) is true log a trace/debug with a stable
prefix (e.g. "external_capability:duplicate") plus the conflicting provider.id;
use the project logging crate (log or tracing) consistently and keep messages
machine-grep-friendly and concise to aid config diagnosis.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b8c244e-2125-4803-add9-d54f121ccb9e

📥 Commits

Reviewing files that changed from the base of the PR and between f8c9698 and 13f8af8.

📒 Files selected for processing (5)
  • src/openhuman/config/schema/mod.rs
  • src/openhuman/config/schema/tools.rs
  • src/openhuman/config/schema/types.rs
  • src/openhuman/external_capabilities/mod.rs
  • src/openhuman/mod.rs

Comment thread src/openhuman/external_capabilities/mod.rs Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/external_capabilities/registry.rs`:
- Around line 38-70: Update ExternalCapabilityRegistry::from_config to emit
flow-level debug diagnostics: add an entry log at start and an exit log before
returning, and log branch outcomes each time
ExternalCapabilityProvider::from_config succeeds or fails and when a duplicate
is detected; include stable prefixes like "[external_capability][registry]" and
correlation fields such as total_providers (config.providers.len()),
accepted_count, rejected_count, duplicate_count, and a normalized provider id
list or the provider.id for each processed item. Ensure the existing debug calls
are augmented (or replaced) to follow this pattern and increment the
accepted/rejected/duplicate counters as you process providers so the exit log
reports the final counts and any aggregated errors in Self { providers, errors
}.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7c109b51-9f04-412f-babb-6d7afcbcb5d2

📥 Commits

Reviewing files that changed from the base of the PR and between 13f8af8 and d91b5ef.

📒 Files selected for processing (3)
  • src/openhuman/external_capabilities/mod.rs
  • src/openhuman/external_capabilities/registry.rs
  • src/openhuman/external_capabilities/types.rs
✅ Files skipped from review due to trivial changes (1)
  • src/openhuman/external_capabilities/mod.rs

Comment on lines +38 to +70
pub fn from_config(config: &ExternalCapabilityProvidersConfig) -> Self {
let mut providers = BTreeMap::new();
let mut errors = Vec::new();

for provider in &config.providers {
match ExternalCapabilityProvider::from_config(provider) {
Ok(provider) => {
if providers.contains_key(&provider.id) {
log::debug!(
"[external_capability] duplicate provider_id={}",
provider.id
);
errors.push(format!(
"duplicate external capability provider id `{}`",
provider.id
));
} else {
providers.insert(provider.id.clone(), provider);
}
}
Err(err) => {
log::debug!(
"[external_capability] invalid provider_config_id={} error={}",
provider.id,
err
);
errors.push(err);
}
}
}

Self { providers, errors }
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add full flow-level diagnostics in registry construction.

from_config currently logs only some error paths. Per guideline, new flow diagnostics should include entry/exit and branch outcomes with stable prefixes and correlation fields (e.g., total provider count, accepted/rejected/duplicate counts, normalized provider IDs).

Suggested logging expansion
 pub fn from_config(config: &ExternalCapabilityProvidersConfig) -> Self {
+    log::debug!(
+        "[domain] [external_capability] registry_build_start providers_count={}",
+        config.providers.len()
+    );
     let mut providers = BTreeMap::new();
     let mut errors = Vec::new();
+    let mut accepted = 0usize;
+    let mut rejected = 0usize;
+    let mut duplicates = 0usize;

     for provider in &config.providers {
         match ExternalCapabilityProvider::from_config(provider) {
             Ok(provider) => {
                 if providers.contains_key(&provider.id) {
+                    duplicates += 1;
                     log::debug!(
-                        "[external_capability] duplicate provider_id={}",
+                        "[domain] [external_capability] duplicate provider_id={}",
                         provider.id
                     );
                     errors.push(format!(
                         "duplicate external capability provider id `{}`",
                         provider.id
                     ));
                 } else {
+                    accepted += 1;
+                    log::debug!(
+                        "[domain] [external_capability] accepted provider_id={} trusted={} enabled={}",
+                        provider.id,
+                        provider.trusted,
+                        provider.enabled
+                    );
                     providers.insert(provider.id.clone(), provider);
                 }
             }
             Err(err) => {
+                rejected += 1;
                 log::debug!(
-                    "[external_capability] invalid provider_config_id={} error={}",
+                    "[domain] [external_capability] invalid provider_config_id={} error={}",
                     provider.id,
                     err
                 );
                 errors.push(err);
             }
         }
     }

+    log::debug!(
+        "[domain] [external_capability] registry_build_end accepted={} duplicates={} rejected={} errors={}",
+        accepted,
+        duplicates,
+        rejected,
+        errors.len()
+    );
     Self { providers, errors }
 }

As per coding guidelines, “Debug logging must follow these rules: default to verbose diagnostics on new/changed flows; log entry/exit, branches… and errors… All changes lacking diagnosis logging are incomplete.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn from_config(config: &ExternalCapabilityProvidersConfig) -> Self {
let mut providers = BTreeMap::new();
let mut errors = Vec::new();
for provider in &config.providers {
match ExternalCapabilityProvider::from_config(provider) {
Ok(provider) => {
if providers.contains_key(&provider.id) {
log::debug!(
"[external_capability] duplicate provider_id={}",
provider.id
);
errors.push(format!(
"duplicate external capability provider id `{}`",
provider.id
));
} else {
providers.insert(provider.id.clone(), provider);
}
}
Err(err) => {
log::debug!(
"[external_capability] invalid provider_config_id={} error={}",
provider.id,
err
);
errors.push(err);
}
}
}
Self { providers, errors }
}
pub fn from_config(config: &ExternalCapabilityProvidersConfig) -> Self {
log::debug!(
"[domain] [external_capability] registry_build_start providers_count={}",
config.providers.len()
);
let mut providers = BTreeMap::new();
let mut errors = Vec::new();
let mut accepted = 0usize;
let mut rejected = 0usize;
let mut duplicates = 0usize;
for provider in &config.providers {
match ExternalCapabilityProvider::from_config(provider) {
Ok(provider) => {
if providers.contains_key(&provider.id) {
duplicates += 1;
log::debug!(
"[domain] [external_capability] duplicate provider_id={}",
provider.id
);
errors.push(format!(
"duplicate external capability provider id `{}`",
provider.id
));
} else {
accepted += 1;
log::debug!(
"[domain] [external_capability] accepted provider_id={} trusted={} enabled={}",
provider.id,
provider.trusted,
provider.enabled
);
providers.insert(provider.id.clone(), provider);
}
}
Err(err) => {
rejected += 1;
log::debug!(
"[domain] [external_capability] invalid provider_config_id={} error={}",
provider.id,
err
);
errors.push(err);
}
}
}
log::debug!(
"[domain] [external_capability] registry_build_end accepted={} duplicates={} rejected={} errors={}",
accepted,
duplicates,
rejected,
errors.len()
);
Self { providers, errors }
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/external_capabilities/registry.rs` around lines 38 - 70, Update
ExternalCapabilityRegistry::from_config to emit flow-level debug diagnostics:
add an entry log at start and an exit log before returning, and log branch
outcomes each time ExternalCapabilityProvider::from_config succeeds or fails and
when a duplicate is detected; include stable prefixes like
"[external_capability][registry]" and correlation fields such as total_providers
(config.providers.len()), accepted_count, rejected_count, duplicate_count, and a
normalized provider id list or the provider.id for each processed item. Ensure
the existing debug calls are augmented (or replaced) to follow this pattern and
increment the accepted/rejected/duplicate counters as you process providers so
the exit log reports the final counts and any aggregated errors in Self {
providers, errors }.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add trusted external capability provider registry

1 participant