Skip to content

Add Keenable search and fetch provider - #10

Open
ilya-bogin-keenable wants to merge 2 commits into
tinyhumansai:mainfrom
keenableai:add-keenable-provider
Open

ilya-bogin-keenable wants to merge 2 commits into
tinyhumansai:mainfrom
keenableai:add-keenable-provider

Conversation

@ilya-bogin-keenable

Copy link
Copy Markdown

Summary

I work at Keenable. This adds Keenable as a direct provider with two tools: keenable_search for the search role and keenable_fetch for the contents role. It needs no credential. Once the host enables it with a direct route, it calls Keenable's keyless /v1/search/public and /v1/fetch/public, which are rate limited per IP; for a desktop agent that means each user's own IP and no account to set up. A configured credential switches both tools to the keyed /v1/search and /v1/fetch (sent as X-API-Key) for higher limits.

Every request carries X-Keenable-Title: tinysearch, which the keyless endpoints require. It names the module only, with no user or host identifier. Search sends query, max_results (1-20, defaulting to the configured count) and optional site, published_after and published_before, and asks for 1,200-character snippets since normalization keeps no more than that. Results map snippet (falling back to description) and published_at onto the normalized fields. keenable_fetch reads each URL from Keenable's index and, on a 404 for a page that is not indexed, fetches it live from the source. Failed pages are counted in provider_data.failed_count. When every page fails, the first failure's code is returned, so a 429 stays rate_limited and the contents role falls back.

Related issue

None

API or behavior changes

Additive, not breaking. PROVIDERS gains keenable. It is usable on the direct route without a credential (like SearXNG, but with no base URL needed), and it serves the search and contents roles, last in both default orders. Nothing changes for existing providers or configurations. I left CONTRACT_VERSION at 2.0; tell me if a new provider should bump it.

Validation

Commands actually run, with their outcome:

  • cargo fmt --all -- --check: clean
  • cargo clippy --all-targets --all-features -- -D warnings: clean on 1.98
  • cargo build --all-targets --all-features: ok
  • cargo test --all-features: 165 passed, 0 failed

.github/scripts/check-file-coverage.sh 90 target/coverage.json passes: keenable.rs is at 100%, and the catalog and roles files are at 98% and 100%. RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features is clean.

A live run with no credential, through SearchService in roles mode with only keenable configured:

tools ["web_search_tool", "web_contents_tool"]
search https://pyguides.dev/tutorials/intermediate-python/asyncio-tutorial | Some("2026-03-07T00:00:00Z") | 970
search https://pyguides.dev/guides/asyncio-basics | Some("2026-03-13T00:00:00Z") | 498
search https://realpython.com/async-io-python/ | Some("2025-07-30T14:00:00Z") | 1103
role Some(Search) provider keenable
fetch https://docs.python.org/3/library/asyncio.html | asyncio — Asynchronous I/O | "# `asyncio` — Asynchronous I/O¶\n\n---\n\nasyncio is a"
fetch https://example.org | Example Domain | "This domain is for use in documentation examples w"
provider_data Some(Object {"failed_count": Number(0)})

(Search lines are URL, publish date and snippet length.)

Tests

Seven tests in provider/direct/keenable/keenable_tests.rs run against a local server:

  • keyless search: path, title header, no key header, body, snippet and description fallback, publish date, a result without a URL dropped
  • keyed search: key header, the configured count clamped to 20, filters forwarded and unknown arguments dropped
  • fetch: one request per URL, then a live retry after a 404
  • keyed fetch with a partial failure counted in failed_count
  • a total failure keeps rate_limited
  • invalid tool, query, URLs and base URL
  • listing without a credential, hidden on the backend route or when disabled

catalog/mod_tests.rs now also pins keenable in the catalog, its roles, its role tools and both default orders.

Documentation

README.md: Keenable added to the role table, plus a paragraph under Built-in providers. MODULE.md: notes that SearXNG and Keenable need no credential.

Once this lands, I'd follow up in OpenHuman with a keenable entry in the search settings (an optional key field), if you want it there.

Checklist

  • The change is focused on one logical change
  • No new #[allow(...)], #[ignore], or relaxed lints
  • No secrets, tokens, or .env contents in the diff or the description

@tinysweeper

tinysweeper Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

This update revises the Keenable provider pull request (previously at head 83fb760, state 'changes requested'). The diff now includes an expanded comment in `configured_provider_tools` explaining that Keenable's keyless access is gated by the host's explicit enabled Direct entry (a default configuration lists nothing), and the tool-visibility test file is present, covering the hidden-by-default, backend-route, and disabled cases. The tests and description lanes state the previously raised authorization concern is resolved and the change is ready to merge. However, the critique and security lanes still actively raise authorization findings on this head: 'Require authorization before enabling direct Keenable access' (rules `missing-authorization`/`authorization-bypass`/`authorization-gate`) on `crates/tinysearch-bus/src/search/catalog/mod.rs` and `crates/tinysearch/src/provider/direct/keenable/keenable_tests.rs`, plus a critique finding 'Add the missing external catalog tests' (`missing-external-test`) on the catalog module. These unresolved findings should be reconciled before merge.

State: Changes requested
Priority: critical
Reviewed head: 0d0cab758cc3
Updated: 1791285407 (Unix time)

Review snapshot

Change surface Files Review signal Count
Production 5 Active findings 5
Tests 2 Noted findings 0
Documentation 2 Resolved findings 7
Configuration 0 Pending checks/questions 0

Completeness: Complete
Test assessment: Test coverage is assessed from changed tests and lane evidence; execution is not claimed without trusted check data.

What changed

The same Keenable provider implementation as the prior revision: `crates/tinysearch/src/provider/direct/keenable.rs` implements search (posting the query with optional `site`, `published_after`, `published_before` filters, max_results clamped to 1-20 with default 5, 1,200-character snippets) and fetch (up to 10 URLs, a 404 retry with `live=true`, `failed_count` accounting, and the first error's classification when every page fails), switching between keyless `/public` endpoints and keyed endpoints via `X-API-Key`, with `X-Keenable-Title: tinysearch` on every request. The catalog change in `crates/tinysearch-bus/src/search/catalog/mod.rs` now carries an explanatory comment that Keenable, like SearXNG, has no credential to gate on — the host's own enabled entry is the opt-in, calls go only to Keenable or the host's base URL, and a credential only raises limits — before the `ProviderRoute::Direct if name == "keenable" => true` arm. Role wiring, default provider orders, documentation, and dispatch changes are unchanged from the prior revision.

Features

  • Added — Keenable direct provider (search and fetch tools): Enables web search and page fetching without a provider credential; keyless requests use Keenable's per-IP rate-limited public endpoints and a configured credential switches to the keyed endpoints with higher limits. Every request identifies the caller with `X-Keenable-Title: tinysearch`. Note: the critique and security lanes still flag authorization gating for this keyless direct access on the current head. (crates/tinysearch/src/provider/direct/keenable.rs, crates/tinysearch/src/provider/direct/mod.rs#pub(super) async fn run(, crates/tinysearch/src/provider/mod.rs#impl BuiltinProvider {, README.md#it with a `base_url` and a direct route. It requests `/search?format=json`,)
  • Added — Keenable catalog registration and role wiring: Adds `keenable_search` and `keenable_fetch` tool specs, marks Keenable usable on the Direct route without a credential (now with an explicit comment framing the host's enabled entry as the opt-in), maps it to the Search and Contents roles, and appends it last in both roles' default provider orders. (crates/tinysearch-bus/src/search/catalog/mod.rs#pub const PROVIDERS: &[&str] = &[, crates/tinysearch-bus/src/search/catalog/mod.rs#fn direct_provider_specs() -> BTreeMap<String, Vec<ToolSpec>> {, crates/tinysearch-bus/src/search/catalog/mod.rs#pub fn configured_provider_tools(, crates/tinysearch-bus/src/search/catalog/roles.rs#pub fn provider_roles(provider: &str) -> &'static [Role] {, crates/tinysearch-bus/src/search/catalog/roles.rs#pub fn default_role_providers(role: Role) -> &'static [&'static str] {, crates/tinysearch-bus/src/search/catalog/roles.rs#pub fn role_provider_tool(role: Role, provider: &str) -> Option<&'static str> {)
  • Added — Fetch partial-failure handling and live retry: `keenable_fetch` reads up to 10 URLs, retries an unindexed (404) page live from the source, counts failed pages in `provider_data.failed_count`, and returns the first failure's error classification only when every page fails so the contents role can fall back. (crates/tinysearch/src/provider/direct/keenable.rs, README.md#it with a `base_url` and a direct route. It requests `/search?format=json`,)

Tests

  • unit — HTTP-level tests using a local TCP-socket mock verify endpoint selection (public vs keyed), the `X-Keenable-Title` and `X-API-Key` headers, request bodies including max_results clamping and filter passthrough, result mapping (snippet fallback, published date, dropped entries without URL), the 404-then-live retry, partial-failure `failed_count` accounting, and total-failure classification (rate limits stay fallback-eligible).: Cited as present in the diff; not executed by the review. (crates/tinysearch/src/provider/direct/keenable/keenable_tests.rs)
  • unit — Error-path tests cover an unknown tool name, an empty query, empty URLs, and a bad base URL scheme, all failing before any network call.: Cited as present in the diff; not executed by the review. (crates/tinysearch/src/provider/direct/keenable/keenable_tests.rs)
  • unit — Tool-visibility test asserts Keenable tools appear without a credential only when enabled on the Direct route, and that they surface as `web_search_tool` and `web_contents_tool` in Roles mode; hidden on the Backend route, when disabled, and in a default configuration.: Cited as present in the diff; the tests lane describes this gating as the resolution of the earlier authorization concern, though the critique and security lanes still carry active authorization findings on this head. (crates/tinysearch/src/provider/direct/keenable/keenable_tests.rs)

Findings

  • critical · critique · Add the missing external catalog tests — The new Keenable provider specifications are registered without adding the external catalog test file required by the repository's test layout. If the existing module declaration r (crates/tinysearch\-bus/src/search/catalog/mod\.rs:204)
  • high · critique · Require authorization before enabling direct Keenable access — This makes every explicitly configured direct Keenable provider active even when `explicit.credential` is absent. A caller can therefore invoke Keenable's direct tools without auth (crates/tinysearch\-bus/src/search/catalog/mod\.rs:311)
  • high · critique · Require authorization before enabling direct Keenable access — This test explicitly accepts a default `ProviderConfig` with no credential and expects the direct Keenable tools to be listed. That configuration permits callers to invoke the publ (crates/tinysearch/src/provider/direct/keenable/keenable\_tests\.rs:288)
  • high · security · Require authorization before enabling direct Keenable access — This makes any explicitly enabled direct Keenable provider available without checking a credential or another authorization capability, unlike the other keyed direct providers. Bec (crates/tinysearch\-bus/src/search/catalog/mod\.rs:311)
  • high · security · Require authorization before enabling direct Keenable access — This test explicitly codifies that a default Keenable configuration with no credential exposes both direct tools. A caller can therefore discover and invoke direct Keenable access (crates/tinysearch/src/provider/direct/keenable/keenable\_tests\.rs:291)

Resolved this pass

  • Add the referenced external test file
  • Add the referenced external test file
  • Add the referenced external test file
  • Add the referenced external test file
  • Require authorization before enabling direct Keenable access
  • Add the referenced external test file
  • Require authorization before enabling direct Keenable access

Before merge

  • Address Add the missing external catalog tests (crates/tinysearch\-bus/src/search/catalog/mod\.rs).
  • Address Require authorization before enabling direct Keenable access (crates/tinysearch\-bus/src/search/catalog/mod\.rs).
  • Address Require authorization before enabling direct Keenable access (crates/tinysearch/src/provider/direct/keenable/keenable\_tests\.rs).
  • Address Require authorization before enabling direct Keenable access (crates/tinysearch\-bus/src/search/catalog/mod\.rs).
  • Address Require authorization before enabling direct Keenable access (crates/tinysearch/src/provider/direct/keenable/keenable\_tests\.rs).

How this fits together

flowchart LR
  n0["configured_provider_tools<br/>changed<br/>3 findings"]:::blocking
  n1["direct_provider_specs<br/>changed<br/>3 findings"]:::blocking
  n2["catalog_and_selection_are_stable<br/>changed"]:::changed
  n3["provider_tool_specs"]:::impacted
  n4["default"]:::impacted
  n5["role_config"]:::impacted
  n6["parallel_is_direct_only"]:::impacted
  n7["backend_failure_envelope_is_redacted"]:::impacted
  n8["keyed"]:::impacted
  n2 -->|calls| n3
  n2 -->|tests| n3
  n2 -->|calls| n4
  n2 -->|tests| n4
  n3 -->|calls| n1
  n5 -->|calls| n4
  n5 -->|calls| n8
  n6 -->|calls| n0
  n6 -->|tests| n0
  n6 -->|calls| n3
  n6 -->|tests| n3
  n6 -->|calls| n4
  n6 -->|tests| n4
  n6 -->|calls| n8
  n6 -->|tests| n8
  n7 -->|calls| n4
  n7 -->|tests| n4
  n8 -->|calls| n4
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading
Agent review details

critique

  • Conclusion: Failure
  • Scope reviewed: all assigned evidence
  • Lane summary: Reviewed 2 files; 3 findings. _Code retrieval was unavailable (model: ladder embeddings returned 400 Bad Request: {"error":{"message":"unknown ladder vectors; known ladders are flash (also chat-v1, flash-v1), instant (also no-think, instant-v1), reasoning (also deepseek), max-reasoning (also max-reasoning-v1), deepseek-flash (also reasoning-v1, agentic-v1), deep (also luna), scribe, uncensored, vectors-oai3 (also embeddings-oai3-v1), vision (also vision-v1, multimodal-v1), image (also images-v1, image-v1), vi), so this review saw the diff alone._ _Memory was unavailable (model: cortex: v1/recall: error sending request for url (http://cortexdb:3141/v1/recall\)\), so this review ran without it._
  • Evidence: crates/tinysearch\-bus/src/search/catalog/mod\.rs — Add the missing external catalog tests
  • Evidence: crates/tinysearch\-bus/src/search/catalog/mod\.rs — Require authorization before enabling direct Keenable access
  • Evidence: crates/tinysearch/src/provider/direct/keenable/keenable\_tests\.rs — Require authorization before enabling direct Keenable access

security

  • Conclusion: Failure
  • Scope reviewed: all assigned evidence
  • Lane summary: Reviewed 2 files; 2 findings. (1 observation(s) grouped into shared inline comments) _Code retrieval was unavailable (model: ladder embeddings returned 400 Bad Request: {"error":{"message":"unknown ladder vectors; known ladders are flash (also chat-v1, flash-v1), instant (also no-think, instant-v1), reasoning (also deepseek), max-reasoning (also max-reasoning-v1), deepseek-flash (also reasoning-v1, agentic-v1), deep (also luna), scribe, uncensored, vectors-oai3 (also embeddings-oai3-v1), vision (also vision-v1, multimodal-v1), image (also images-v1, image-v1), vi), so this review saw the diff alone._ _Memory was unavailable (model: cortex: v1/recall: error sending request for url (http://cortexdb:3141/v1/recall\)\), so this review ran without it._
  • Evidence: crates/tinysearch\-bus/src/search/catalog/mod\.rs — Require authorization before enabling direct Keenable access
  • Evidence: crates/tinysearch/src/provider/direct/keenable/keenable\_tests\.rs — Require authorization before enabling direct Keenable access

tests

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The description lane confirms the previously missing test file is now present, that direct access is gated on the host's explicit enabled entry (hidden by default, on the backend route, and when disabled), resolving both earlier findings, and that the description matches the diff.
  • Positive: The new tests drive real HTTP through a local socket mock and assert endpoint choice, headers, request bodies, retry behavior, partial-failure accounting, and error classification, so regressions in the keyless/keyed switching would be caught.
  • Lane summary: The new Keenable provider is properly gated behind an explicit host-enabled Direct entry (previously raised authorization concern resolved), and the previously missing test file now exists with real behavioural coverage: endpoint choice by credential, headers, filter passthrough, the 404→live retry, partial-failure counting, and the all-failed classification path are all exercised against a local mock server. The change looks sound and safe to merge. _Code retrieval was unavailable (model: ladder embeddings returned 400 Bad Request: {"error":{"message":"unknown ladder vectors; known ladders are flash (also chat-v1, flash-v1), instant (also no-think, instant-v1), reasoning (also deepseek), max-reasoning (also max-reasoning-v1), deepseek-flash (also reasoning-v1, agentic-v1), deep (also luna), scribe, uncensored, vectors-oai3 (also embeddings-oai3-v1), vision (also vision-v1, multimodal-v1), image (also images-v1, image-v1), vi), so this review saw the diff alone._ _Memory was unavailable (model: cortex: v1/recall: error sending request for url (http://cortexdb:3141/v1/recall\)\), so this review ran without it._

commits

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: Nothing sensitive found in what this pull request commits.

description

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: The Keenable provider is complete: the previously missing test file is now present, and direct access is gated on the host's explicit enabled entry (hidden by default, on the backend route, and when disabled), which resolves both earlier findings. Tests cover the wire behavior, and the description matches the diff. Ready to merge. _Code retrieval was unavailable (model: ladder embeddings returned 400 Bad Request: {"error":{"message":"unknown ladder vectors; known ladders are flash (also chat-v1, flash-v1), instant (also no-think, instant-v1), reasoning (also deepseek), max-reasoning (also max-reasoning-v1), deepseek-flash (also reasoning-v1, agentic-v1), deep (also luna), scribe, uncensored, vectors-oai3 (also embeddings-oai3-v1), vision (also vision-v1, multimodal-v1), image (also images-v1, image-v1), vi), so this review saw the diff alone._ _Memory was unavailable (model: cortex: v1/recall: error sending request for url (http://cortexdb:3141/v1/recall\)\), so this review ran without it._

e2e

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: No end-to-end harness in this repository: no e2e test files and no e2e workflow.
Evidence and run details
  • Models: gpt-5.6-luna, glm-5.3-flash
  • Spend: $0.009922
  • Tokens: 194338 input · 11705 output · 9439 cached · 0 embedding
Head State Pass summary
83fb760ef8ae changes requested 2 active finding(s), 0 resolved finding(s) (at 1791285128)
0d0cab758cc3 changes requested 5 active finding(s), 7 resolved finding(s) (at 1791285407)

tinysweeper 0.1.0

@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 03859ce8-64a6-4ca5-931f-ee5862bf1aa9
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Requesting changes: 2 lane(s) blocking, worst finding is critical.

Fix or reply to the findings below and push. The next review clears this automatically once they are gone — you should not need to dismiss anything by hand.

             $0.0069 · 301,522 in / 14,881 out · 27,179 cached (9%)  · gpt-5.6-luna, glm-5.3-flash
critique:    $0.0027 · 150,449 in / 8,515 out  · 14,389 cached (10%) · gpt-5.6-luna, glm-5.3-flash
security:    $0.0013 · 110,637 in / 3,736 out  · 12,790 cached (12%) · gpt-5.6-luna
tests:       $0.0009 · 13,298 in  / 574 out    · 0 cached (0%)       · glm-5.3-flash
description: $0.0009 · 13,723 in  / 318 out    · 0 cached (0%)       · glm-5.3-flash

super::super::http::read_json(response).await
}

#[cfg(test)]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority critical critique confident

Add the referenced external test file

Rust will try to include keenable/keenable_tests.rs when compiling tests, but that file is not present in the complete change shown. As a result, cargo test and test-target builds fail with a missing-module-file error. Add the referenced sibling test file to the pull request, or remove the module declaration if tests are intentionally omitted.

[RULE] missing-module-file ·

ProviderRoute::Direct if name == "searxng" => {
non_empty(explicit.base_url.as_deref())
}
// Keenable has keyless public endpoints; a credential only raises limits.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority high security likely

Require authorization before enabling direct Keenable access

This makes Keenable usable for every direct-route configuration regardless of whether credentials or another explicit authorization signal is present. Because the provider performs network-backed search and fetch operations, callers who can invoke the bus can use the provider without the credential gate applied to other direct providers. Do not unconditionally return true; require the provider's supported authorization/configuration state before advertising or dispatching it.

[RULE] authorization-bypass ·

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved — the review agent found this finding fixed in the new code, as of 0d0cab7.

If this is wrong, reopen the conversation and say so; the finding will be re-raised on the next push if it still reproduces.

Clippy 1.99 flags assert!(x.is_empty()). The catalog comment now says what
gates keyless Keenable: the host's own enabled provider entry.

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Requesting changes: 2 lane(s) blocking, worst finding is critical.

Fix or reply to the findings below and push. The next review clears this automatically once they are gone — you should not need to dismiss anything by hand.

             $0.0099 · 194,338 in / 11,705 out · 9,439 cached (5%)  · gpt-5.6-luna, glm-5.3-flash
critique:    $0.0045 · 85,168 in  / 5,885 out  · 4,070 cached (5%)  · gpt-5.6-luna, glm-5.3-flash
security:    $0.0030 · 52,152 in  / 2,949 out  · 5,369 cached (10%) · gpt-5.6-luna
tests:       $0.0002 · 13,695 in  / 271 out    · 0 cached (0%)      · glm-5.3-flash
description: $0.0002 · 14,120 in  / 492 out    · 0 cached (0%)      · glm-5.3-flash

("querit".into(), querit),
("tavily".into(), tavily),
("seltz".into(), seltz),
("keenable".into(), keenable),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority critical critique likely

Add the missing external catalog tests

The new Keenable provider specifications are registered without adding the external catalog test file required by the repository's test layout. If the existing module declaration references that file, this leaves the crate unable to compile; even if it is not referenced yet, the new wire contracts and in-memory bus behavior are untested. Add the referenced <module>_tests.rs file and cover the new provider schemas and calls.

[RULE] missing-external-test ·

// credential to gate on: the host's own enabled entry for it is the
// opt-in (a default configuration lists nothing), and calls go only to
// Keenable or the host's base URL. A credential just raises limits.
ProviderRoute::Direct if name == "keenable" => true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority high critique confident

Require authorization before enabling direct Keenable access

This makes every explicitly configured direct Keenable provider active even when explicit.credential is absent. A caller can therefore invoke Keenable's direct tools without authorization, contrary to the credential gate used for keyed direct providers; a public endpoint or a credential that merely raises limits does not establish that the host is authorized to spend its quota. Gate this route on the configured credential, or otherwise require the authorization mechanism used by the Keenable provider before returning true.


Additional security observation

priority high confident

Require authorization before enabling direct Keenable access

[RULE] authorization-bypass

This makes any explicitly enabled direct Keenable provider available without checking a credential or another authorization capability, unlike the other keyed direct providers. Because the catalog controls which provider tools callers can invoke, an enabled configuration can expose Keenable's network-backed search and fetch operations without an authorization gate. Require the appropriate host authorization or credential before returning these tools.

[RULE] missing-authorization ·

let mut config = SearchConfig::default();
config.presentation.mode = PresentationMode::AllTools;
assert_eq!(tool_names(&config).len(), 0);
config

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority high critique confident

Require authorization before enabling direct Keenable access

This test explicitly accepts a default ProviderConfig with no credential and expects the direct Keenable tools to be listed. That configuration permits callers to invoke the public endpoints merely by registering the provider, so there is no authorization gate before exposing direct provider access. Require an authorized credential or an explicit opt-in before listing and executing these tools; otherwise an untrusted caller can consume Keenable's public quota through the application.

[RULE] authorization-gate ·

config
.providers
.insert("keenable".into(), ProviderConfig::default());
assert_eq!(tool_names(&config), ["keenable_search", "keenable_fetch"]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority high security confident

Require authorization before enabling direct Keenable access

This test explicitly codifies that a default Keenable configuration with no credential exposes both direct tools. A caller can therefore discover and invoke direct Keenable access without an authorization gate. Require an authorized configuration or caller identity before registering these tools, and update the test to assert that unauthorized direct access is not exposed.

[RULE] missing-authorization ·

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant