- restore Lark constructor wiring and platform-specific builders used by channel-lark builds\n- re-export syscall anomaly detector types from security module\n- suppress unauthorized Telegram prompts for unmentioned group messages when mention_only=true (still allow /bind)\n\nRefs: #1959\nRefs: #1960
- security: honor explicit command paths in allowed_commands list
- security: respect workspace_only=false in resolved path checks
- config: enforce 0600 permissions on every config save (unix)
- config: reject temp-directory paths in active workspace marker
- provider: preserve reasoning_content in tool-call conversation history
- provider: add allow_user_image_parts parameter for minimax compatibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded OPENROUTER_API_KEY hint with provider-aware logic:
- keyless local providers (ollama, llamacpp, etc.) show chat/gateway/status hints
- device-flow providers (copilot, gemini, openai-codex) show OAuth/first-run hint
- all other providers show the correct provider-specific env var via provider_env_var()
Also adds canonical alias "github-copilot" -> "copilot" in canonical_provider_name(),
and a new provider_supports_device_flow() helper with accompanying test.
Additionally fixes pre-existing compile blockers that prevented CI from running:
- fix(security): correct raw string literals in leak_detector.rs that terminated
early due to unescaped " inside r"..." (use r#"..."# instead)
- fix(gateway): add missing wati: None in two test AppState initializations
- fix(gateway): use serde::Deserialize path on WatiVerifyQuery struct
- fix(security): add #[allow(unused_imports)] on new pub use re-exports in mod.rs
- fix(security): remove unused serde::{Deserialize, Serialize} import
- chore: apply cargo fmt to files that had pending formatting diffs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Addresses the unbounded-map gap left by #951: entries below the lockout
threshold (count < MAX_PAIR_ATTEMPTS, lockout = None) were never evicted,
allowing distributed brute-force (>1024 unique IPs, <5 attempts each) to
permanently fill the tracking map and disable accounting for new attackers.
Hardening delta on top of #951:
- Replace raw tuple with typed FailedAttemptState (count, lockout_until,
last_attempt) for clarity and to enable retention-based sweep.
- Bump MAX_TRACKED_CLIENTS from 1024 to 10_000.
- Add 15-min retention sweep (prune_failed_attempts) on 5-min interval.
- Switch lockout from relative (locked_at + elapsed) to absolute
(lockout_until) for simpler and monotonic comparison.
- Add LRU eviction fallback when map is at capacity after pruning.
- Add normalize_client_key() to sanitize whitespace/empty client IDs.
- Add 3 focused tests: per-client reset isolation, bounded map capacity,
and sweep pruning of stale entries.
Supersedes:
- #670 by @fettpl (original hardening branch, rebased as delta)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add `autonomy.allowed_roots` config option that lets the agent
read/write files under additional directory roots outside the
workspace (e.g. shared skills directories, project repos).
Resolved (canonical) paths under any allowed root pass
`is_resolved_path_allowed` alongside the workspace itself.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address clippy lints (redundant continue, as-cast, match arms, elided
lifetimes, format vs write!) and reformat long cfg attributes and assert
macros to pass `cargo fmt --check` and `cargo clippy -D warnings`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>