Replace the dynamic error message in the webhook JSON parsing error
path with a static message. Previously, the raw JsonRejection error
from axum/serde was interpolated into the HTTP response, potentially
exposing internal parsing details to unauthenticated callers.
The detailed error is now logged server-side via tracing::warn for
debugging, while the client receives a generic "Invalid JSON body"
message.
Closes#356
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the rate limit budget consumption (record_action) to immediately
after the path allowlist check but before canonicalization. Previously,
an attacker could probe whether arbitrary paths exist via canonicalize
errors without consuming any rate limit budget, since record_action
was only called after the file size check.
Now every request that passes the basic path validation consumes rate
limit budget, regardless of whether the file exists.
Closes#354
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a sweep mechanism that removes stale IP entries from the rate
limiter's HashMap every 5 minutes. Previously, IPs that made a single
request and never returned would accumulate indefinitely, causing
unbounded memory growth proportional to unique client IPs.
The sweep runs inline during allow() calls — no background task needed.
A last_sweep timestamp ensures the full-map scan only happens once per
sweep interval, keeping amortized overhead minimal.
Closes#353
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace unbounded HashSet<String> with a BoundedSeenSet that evicts
the oldest message IDs (FIFO) when the 100k capacity is reached. This
prevents memory growth proportional to email volume over the process
lifetime, capping the set at ~100k entries regardless of runtime.
Closes#349
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A duplicate ModelCommands enum was introduced in a recent merge,
causing E0119/E0428 compile errors on CI (Rust 1.92).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sanitize_headers was replacing sensitive header values with
***REDACTED*** before passing them to the actual HTTP request,
breaking any authenticated API call. Split into parse_headers
(preserves original values for the request) and
redact_headers_for_display (returns redacted copy for output/logging).
Closes#348
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Fireworks API endpoint requires /v1/chat/completions, but the
base URL was missing the /v1 path segment, causing 404 errors and
triggering a broken responses fallback.
Fix: Add /v1 to base URL so correct endpoint is built:
https://api.fireworks.ai/inference/v1/chat/completions
Unifies scheduled task capabilities and consolidates overlapping implementations from #337 and #338 into a single security-first integration path.\n\nCo-authored-by: Edvard <ecschoye@stud.ntnu.no>\nCo-authored-by: stawky <stakeswky@gmail.com>
Implement Lark/Feishu as a new channel for ZeroClaw (Issue #164).
- Add LarkChannel with Channel trait impl (name, listen, send)
- listen: HTTP server (axum) for event callback with URL verification
(challenge response) and im.message.receive_v1 text message parsing
- send: POST /open-apis/im/v1/messages with tenant_access_token auth
- get_tenant_access_token with caching and auto-refresh on 401
- Allowlist filtering by open_id (same pattern as other channels)
- Add LarkConfig to schema (app_id, app_secret, verification_token, port, allowed_users)
- Register lark in channel list, doctor, and start_channels
- 18 unit tests: config serde, allowlist, channel name, message parsing,
edge cases (unicode, missing fields, invalid JSON, wrong event type)
- Fix pre-existing SchedulerConfig compile error on main
- Add model_fallbacks and api_keys to ReliabilityConfig
- Implement per-model fallback chain in ReliableProvider
- Add API key rotation on auth failures (401/403)
- Add retry-after header parsing and exponential backoff
- Integrate failover into chat_with_system and chat_with_history
- 20 unit tests covering failover, rotation, and retry logic
Fixes#309 - Composio v2 endpoint has been discontinued. Updated to v3
endpoint which is the current supported version.
Composio v2 API is no longer available, causing all Composio tool
executions to fail. This updates the base URL to use v3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch Provider trait methods to return structured ChatResponse
- Map OpenAI-compatible tool_calls into shared ToolCall type
- Update reliable/router wrappers and provider tests for new interface
- Make agent loop prefer structured tool calls with text fallback parsing
- Adapt gateway replies to structured responses with safe tool-call fallback
The tool use protocol in channels/mod.rs was using <invoke> tags,
but the parser in agent/loop_.rs only recognizes <tool_call> tags.
This ensures consistency across all entry points.
High-priority fixes:
- Message length validation and splitting (4096 char limit)
- Empty chat_id validation to prevent silent failures
- Health check timeout (5s) to prevent service hangs
Testing infrastructure:
- Comprehensive test suite (20+ automated tests)
- Quick smoke test script
- Test message generator
- Complete testing documentation
All changes are backward compatible.
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes#294 - Updates MiniMax model names from the old ABAB 6.5 series to
the current M2.5/M2.1 series.
- Updated wizard model selection for MiniMax provider
- Fixed DiscordConfig test cases to include new listen_to_bots field
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes#284 - Tool call format was missing from the system prompt in
channel, daemon, and gateway modes. This caused LLMs to not know how
to properly invoke tools when using these modes.
The tool use protocol with <invoke> tags and JSON payload format now
matches the implementation in agent loop mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>