Skip to content

fix: more strict check for registry to avoid false positives#2222

Merged
serrrfirat merged 4 commits intonearai:stagingfrom
gagdiez:fix/search-for-registry
Apr 14, 2026
Merged

fix: more strict check for registry to avoid false positives#2222
serrrfirat merged 4 commits intonearai:stagingfrom
gagdiez:fix/search-for-registry

Conversation

@gagdiez
Copy link
Copy Markdown
Contributor

@gagdiez gagdiez commented Apr 9, 2026

Summary

By default ironclaw gets installed in ~/.cargo/bin/ironclaw, if the user happens to try to compile anything (e.g. their own tool) then the ~/.cargo/registry folder gets created, which makes ironclaw think that it found an (empty) registry, and thus stops being able to do list or install tools from its internal registry

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

Closes #2221

Validation

  • cargo fmt --all -- --check
  • cargo test
  • cargo clippy --all --benches --tests --examples --all-features -- -D warnings
  • cargo build
  • Relevant tests pass:
  • cargo test --features integration if database-backed or integration behavior changed
  • Manual testing: Built, created a registry folder on parent directory, and tested that ironclaw registry list still worked
  • If a coding agent was used and supports it, review-pr or pr-shepherd --fix was run before requesting review

Security Impact

None

Database Impact

None

Blast Radius

Registry load

Rollback Plan

Revert is_registry to simply check for is_dir


Review track: A or B

By default ironclaw gets installed in ~/.cargo/bin/ironclaw, if
the user happens to try to compile anything (e.g. their own tool)
then the ~/.cargo/registry folder gets created, which makes
ironclaw think that it found an (empty) registry, and thus stops
being able to do list or install tools from its internal registry
Copilot AI review requested due to automatic review settings April 9, 2026 22:21
@github-actions github-actions Bot added size: M 50-199 changed lines risk: low Changes to docs, tests, or low-risk modules contributor: regular 2-5 merged PRs labels Apr 9, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes false-positive detection of an on-disk registry/ directory (notably ~/.cargo/registry) so ironclaw registry list/install continues to work by falling back to the embedded registry when a real internal registry isn’t present.

Changes:

  • Replace candidate.is_dir() checks with a stricter is_registry() predicate during registry discovery.
  • Add unit tests covering is_registry() accept/reject cases.
  • Update build.rs to add directory-level cargo:rerun-if-changed entries for registry subdirectories.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/registry/catalog.rs Introduces is_registry() and applies it in find_dir(); adds tests for the new predicate.
build.rs Adds directory-level Cargo rerun triggers for registry subdirectories to detect add/remove changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/registry/catalog.rs
Comment on lines +144 to +154
/// i.e. it contains `_bundles.json` or at least one of the known subdirectories
/// (`tools/`, `channels/`, `mcp-servers/`). This prevents accidentally matching
/// unrelated directories named "registry" such as `~/.cargo/registry/`.
fn is_registry(dir: &Path) -> bool {
if !dir.is_dir() {
return false;
}
dir.join("_bundles.json").is_file()
|| dir.join("tools").is_dir()
|| dir.join("channels").is_dir()
|| dir.join("mcp-servers").is_dir()
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The is_registry heuristic will treat any directory named registry that merely contains an empty tools/, channels/, or mcp-servers/ subdirectory as a valid registry. That can still lead to the original failure mode (finding a “valid” registry that contains no manifests) if a user/project happens to have registry/tools present but empty or unrelated. Consider tightening this to require _bundles.json OR at least one *.json manifest file under one of the known subdirectories (e.g., via read_dir + extension check).

Suggested change
/// i.e. it contains `_bundles.json` or at least one of the known subdirectories
/// (`tools/`, `channels/`, `mcp-servers/`). This prevents accidentally matching
/// unrelated directories named "registry" such as `~/.cargo/registry/`.
fn is_registry(dir: &Path) -> bool {
if !dir.is_dir() {
return false;
}
dir.join("_bundles.json").is_file()
|| dir.join("tools").is_dir()
|| dir.join("channels").is_dir()
|| dir.join("mcp-servers").is_dir()
/// i.e. it contains `_bundles.json` or at least one manifest file in one of the
/// known subdirectories (`tools/`, `channels/`, `mcp-servers/`). This prevents
/// accidentally matching unrelated directories named "registry" such as
/// `~/.cargo/registry/`.
fn has_json_manifest(dir: &Path, subdir: &str) -> bool {
let manifest_dir = dir.join(subdir);
if !manifest_dir.is_dir() {
return false;
}
let Ok(entries) = std::fs::read_dir(&manifest_dir) else {
return false;
};
entries.flatten().any(|entry| {
entry.path().is_file()
&& entry
.path()
.extension()
.and_then(|ext| ext.to_str())
.map(|ext| ext.eq_ignore_ascii_case("json"))
.unwrap_or(false)
})
}
fn is_registry(dir: &Path) -> bool {
if !dir.is_dir() {
return false;
}
dir.join("_bundles.json").is_file()
|| Self::has_json_manifest(dir, "tools")
|| Self::has_json_manifest(dir, "channels")
|| Self::has_json_manifest(dir, "mcp-servers")

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I actually do not agree with this. Hitting an empty registry/ folder was highly likely (I did it multiple times), hitting an empty registry/tools/ or registry/channels/ or registry/mcp-servers seams unlikely in the wild and thus, in case of doing so, should hint that there is actually an empty registry

with that being said, I do think that the real solution is to change the registry logic, and place it inside the config folder (e.g. ~/.ironclaw/registry), but that is work for a different PR

because of that, I assume that this fix is "good enough" as of right now, except if another human reviewer provides a different opinion

Comment thread src/registry/catalog.rs Outdated
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves the registry directory detection logic by introducing a helper method is_registry that validates directory contents, preventing accidental matches with unrelated directories. It also updates the build script to include additional directory-level watches for registry subdirectories and adds unit tests to verify the new detection logic. I have no further feedback, except for a minor suggestion to convert a regular comment into a documentation comment for consistency.

Comment thread src/registry/catalog.rs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 10, 2026 06:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@serrrfirat serrrfirat merged commit ab1f279 into nearai:staging Apr 14, 2026
14 checks passed
This was referenced Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: regular 2-5 merged PRs risk: low Changes to docs, tests, or low-risk modules size: M 50-199 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Empty registry

3 participants