BREAKING CHANGES: - owlen-core no longer depends on ratatui/crossterm - RemoteMcpClient constructors are now async - MCP path validation is stricter (security hardening) This commit resolves three critical issues identified in project analysis: ## P0-1: Extract TUI dependencies from owlen-core Create owlen-ui-common crate to hold UI-agnostic color and theme abstractions, removing architectural boundary violation. Changes: - Create new owlen-ui-common crate with abstract Color enum - Move theme.rs from owlen-core to owlen-ui-common - Define Color with Rgb and Named variants (no ratatui dependency) - Create color conversion layer in owlen-tui (color_convert.rs) - Update 35+ color usages with conversion wrappers - Remove ratatui/crossterm from owlen-core dependencies Benefits: - owlen-core usable in headless/CLI contexts - Enables future GUI frontends - Reduces binary size for core library consumers ## P0-2: Fix blocking WebSocket connections Convert RemoteMcpClient constructors to async, eliminating runtime blocking that froze TUI for 30+ seconds on slow connections. Changes: - Make new_with_runtime(), new_with_config(), new() async - Remove block_in_place wrappers for I/O operations - Add 30-second connection timeout with tokio::time::timeout - Update 15+ call sites across 10 files to await constructors - Convert 4 test functions to #[tokio::test] Benefits: - TUI remains responsive during WebSocket connections - Proper async I/O follows Rust best practices - No more indefinite hangs ## P1-1: Secure path traversal vulnerabilities Implement comprehensive path validation with 7 defense layers to prevent file access outside workspace boundaries. Changes: - Create validate_safe_path() with multi-layer security: * URL decoding (prevents %2E%2E bypasses) * Absolute path rejection * Null byte protection * Windows-specific checks (UNC/device paths) * Lexical path cleaning (removes .. components) * Symlink resolution via canonicalization * Boundary verification with starts_with check - Update 4 MCP resource functions (get/list/write/delete) - Add 11 comprehensive security tests Benefits: - Blocks URL-encoded, absolute, UNC path attacks - Prevents null byte injection - Stops symlink escape attempts - Cross-platform security (Windows/Linux/macOS) ## Test Results - owlen-core: 109/109 tests pass (100%) - owlen-tui: 52/53 tests pass (98%, 1 pre-existing failure) - owlen-providers: 2/2 tests pass (100%) - Build: cargo build --all succeeds ## Verification - ✓ cargo tree -p owlen-core shows no TUI dependencies - ✓ No block_in_place calls remain in MCP I/O code - ✓ All 11 security tests pass Fixes: #P0-1, #P0-2, #P1-1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
91 lines
2.2 KiB
TOML
91 lines
2.2 KiB
TOML
[workspace]
|
|
resolver = "2"
|
|
members = [
|
|
"crates/owlen-core",
|
|
"crates/owlen-ui-common",
|
|
"crates/owlen-tui",
|
|
"crates/owlen-cli",
|
|
"crates/owlen-providers",
|
|
"crates/mcp/server",
|
|
"crates/mcp/llm-server",
|
|
"crates/mcp/client",
|
|
"crates/mcp/code-server",
|
|
"crates/mcp/prompt-server",
|
|
"crates/owlen-markdown",
|
|
"xtask",
|
|
]
|
|
exclude = []
|
|
|
|
[workspace.package]
|
|
version = "0.2.0"
|
|
edition = "2024"
|
|
authors = ["Owlibou"]
|
|
license = "AGPL-3.0"
|
|
repository = "https://somegit.dev/Owlibou/owlen"
|
|
homepage = "https://somegit.dev/Owlibou/owlen"
|
|
keywords = ["llm", "tui", "cli", "ollama", "chat"]
|
|
categories = ["command-line-utilities"]
|
|
|
|
[workspace.dependencies]
|
|
# Async runtime and utilities
|
|
tokio = { version = "1.0", features = ["full"] }
|
|
tokio-stream = "0.1"
|
|
tokio-util = { version = "0.7", features = ["rt"] }
|
|
futures = "0.3"
|
|
futures-util = "0.3"
|
|
|
|
# TUI framework
|
|
ratatui = { version = "0.29", features = ["palette"] }
|
|
crossterm = "0.28.1"
|
|
tui-textarea = "0.7"
|
|
|
|
# HTTP client and JSON handling
|
|
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "rustls-tls"] }
|
|
serde = { version = "1.0", features = ["derive"] }
|
|
serde_json = { version = "1.0" }
|
|
|
|
# Utilities
|
|
uuid = { version = "1.0", features = ["v4", "serde"] }
|
|
anyhow = "1.0"
|
|
thiserror = "2.0"
|
|
nix = "0.29"
|
|
which = "6.0"
|
|
tempfile = "3.8"
|
|
jsonschema = "0.17"
|
|
aes-gcm = "0.10"
|
|
ring = "0.17"
|
|
keyring = "3.0"
|
|
chrono = { version = "0.4", features = ["serde"] }
|
|
urlencoding = "2.1"
|
|
regex = "1.10"
|
|
sqlx = { version = "0.7", default-features = false, features = ["runtime-tokio-rustls", "sqlite", "macros", "uuid", "chrono", "migrate"] }
|
|
log = "0.4"
|
|
dirs = "5.0"
|
|
serde_yaml = "0.9"
|
|
handlebars = "6.0"
|
|
once_cell = "1.19"
|
|
base64 = "0.22"
|
|
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "gif", "bmp", "webp"] }
|
|
mime_guess = "2.0"
|
|
|
|
# Configuration
|
|
toml = "0.8"
|
|
shellexpand = "3.1"
|
|
|
|
# Database
|
|
sled = "0.34"
|
|
|
|
# For better text handling
|
|
textwrap = "0.16"
|
|
|
|
# Async traits
|
|
async-trait = "0.1"
|
|
|
|
# CLI framework
|
|
clap = { version = "4.0", features = ["derive"] }
|
|
|
|
# Dev dependencies
|
|
tokio-test = "0.4"
|
|
|
|
# For more keys and their definitions, see https://doc.rust-lang.org/cargo/reference/manifest.html
|