[package]
name = "pierre_mcp_server"
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Pierre Fitness API - Multi-protocol fitness data API for LLMs (MCP + A2A)"
repository = "https://github.com/Async-IO/pierre_mcp_server"
keywords = ["mcp", "fitness", "strava", "api", "claude"]
categories = ["api-bindings", "web-programming"]
[lib]
name = "pierre_mcp_server"
path = "src/lib.rs"
# Disable built-in bench harness for lib (we use Criterion benches in benches/ instead)
bench = false
[[bin]]
name = "pierre-mcp-server"
path = "src/bin/pierre-mcp-server.rs"
bench = false
# [[bin]]
# name = "auth-setup"
# path = "src/bin/auth_setup.rs"
[[bin]]
name = "admin-setup"
path = "src/bin/admin_setup.rs"
bench = false
[[bin]]
name = "seed-demo-data"
path = "src/bin/seed_demo_data.rs"
bench = false
# [[bin]]
# name = "serve-docs"
# path = "src/bin/serve_docs.rs"
# NOTE: Temporarily disabled during Warp-to-Axum migration
[features]
default = ["sqlite", "all-providers", "sqlx/migrate"]
sqlite = []
postgresql = ["sqlx/postgres"]
testing = []
telemetry = []
# Provider feature flags - enable/disable individual fitness data providers
provider-strava = []
provider-garmin = []
provider-terra = []
provider-fitbit = []
provider-whoop = []
provider-coros = []
provider-synthetic = []
all-providers = ["provider-strava", "provider-garmin", "provider-terra", "provider-fitbit", "provider-whoop", "provider-coros", "provider-synthetic"]
[profile.dev]
debug = 1
opt-level = 0
overflow-checks = true
[profile.release]
lto = "thin"
codegen-units = 1
panic = "abort"
strip = true
[profile.release-lto]
inherits = "release"
lto = "fat"
[dependencies]
tokio = { version = "1.45", features = ["rt-multi-thread", "macros", "net", "time", "fs", "signal", "io-std", "io-util", "sync"] }
tokio-stream = "0.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"], default-features = false }
reqwest-middleware = "0.3"
anyhow = "1.0"
async-stream = "0.3"
thiserror = "2.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "std", "registry", "json"], default-features = false }
# OpenTelemetry for distributed tracing and request correlation
tracing-opentelemetry = "0.23"
opentelemetry = { version = "0.22", features = ["trace"] }
opentelemetry_sdk = { version = "0.22", features = ["trace", "rt-tokio"] }
# HTTP tracing middleware
tower = { version = "0.5", features = ["util"] }
tower-http = { version = "0.6", features = ["trace", "request-id", "cors", "timeout", "limit", "set-header"] }
async-trait = "0.1"
chrono = { version = "0.4", features = ["serde"] }
base64 = "0.22"
bytes = "1.8"
url = "2.5"
clap = { version = "4.5", features = ["derive", "std"], default-features = false }
dotenvy = "0.15"
# toml = "0.8" # Removed: Environment-only configuration approach
dirs = "5.0"
uuid = { version = "1.11", features = ["v4", "serde"] }
dashmap = "5.5"
urlencoding = "2.1"
sha2 = "0.10"
rand = "0.8"
aes-gcm = "0.10"
# Encryption and database support for multi-tenant
ring = "0.17"
ed25519-dalek = "2.1"
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "sqlite", "postgres", "chrono", "uuid", "derive", "migrate", "macros"], default-features = false }
bcrypt = "0.16"
argon2 = "0.5"
jsonwebtoken = "9.3"
subtle = "2.6"
zeroize = { version = "1.8", features = ["alloc"] }
hex = "0.4"
# HTTP framework: Axum (migrated from Warp)
axum = { version = "0.7", features = ["ws", "json", "query", "macros", "tokio", "http2", "form"], default-features = false }
axum-extra = { version = "0.9", features = ["typed-header"] }
http = "1.0"
futures-util = "0.3"
eventsource-stream = "0.2"
# Pin to compatible version to avoid edition2024 requirement
base64ct = "=1.6.0"
# For documentation server
env_logger = "0.11"
# LRU cache for bounded session storage (DoS prevention)
lru = "0.16"
# Glob pattern matching for cache invalidation
glob = "0.3"
# Regex for PII redaction and pattern matching
regex = "1.11"
# Bitflags for PII redaction feature configuration
bitflags = { version = "2.6", features = ["serde"] }
# Cross-platform system information without unsafe FFI
sysinfo = "0.31"
# Redis client with connection pooling and async support
redis = { version = "0.28", features = ["tokio-comp", "connection-manager", "aio"] }
num-traits = "0.2"
# Rayon for CPU-bound parallel data processing (zone analysis, fitness calculations)
rayon = "1.10"
rsa = "0.9"
x509-parser = "0.18.0"
# TOON format for token-efficient LLM serialization (~40% token reduction vs JSON)
toon-format = "0.2"
rand_chacha = "0.3"
[dev-dependencies]
tempfile = "3.20"
serial_test = "3.1"
tokio-tungstenite = "0.24"
criterion = { version = "0.5", features = ["async_tokio", "html_reports"] }
serde_urlencoded = "0.7"
# ============================================================================
# Benchmark Configuration
# ============================================================================
# Each benchmark suite is defined as a separate [[bench]] entry.
# Run all benchmarks: cargo bench
# Run specific suite: cargo bench --bench intelligence_bench
# Run specific benchmark: cargo bench --bench intelligence_bench -- "training_load"
[[bench]]
name = "intelligence_bench"
harness = false
[[bench]]
name = "cache_bench"
harness = false
[[bench]]
name = "database_bench"
harness = false
[[bench]]
name = "serialization_bench"
harness = false
# ============================================================================
# Linting Configuration (Replaces bash script clippy invocation)
# ============================================================================
# This configuration eliminates the need for custom clippy flags in scripts.
# CI/CD can now simply run `cargo clippy` and these settings are applied.
#
# ZERO TOLERANCE ENFORCEMENT:
# Old: cargo clippy --all-targets --all-features -- \
# -W clippy::all -W clippy::pedantic -W clippy::nursery -D warnings
# New: cargo clippy (reads this config, applies level = "deny")
#
# All clippy warnings are now ERRORS via level = "deny" configuration below.
[lints.rust]
# STRICT UNSAFE CODE POLICY: Zero tolerance with whitelisted exceptions
# - "deny" level: Unsafe code is an ERROR by default everywhere
# - scripts/architectural-validation.sh: Enforces ONLY src/health.rs can use unsafe (Windows FFI)
# - Any unsafe usage outside approved locations FAILS build immediately
# - Approved: Windows health monitoring FFI (GlobalMemoryStatusEx, GetDiskFreeSpaceExW)
unsafe_code = "deny"
# Warn on missing documentation for public APIs
missing_docs = "warn"
[lints.clippy]
# Base configuration: Enable all clippy lint groups at DENY level (zero tolerance)
# Priority -1 ensures these are applied first, then specific overrides below
# All clippy warnings are treated as ERRORS via level = "deny"
all = { level = "deny", priority = -1 }
pedantic = { level = "deny", priority = -1 }
nursery = { level = "deny", priority = -1 }
# ============================================================================
# Critical Denials - Error Handling Anti-Patterns (CLAUDE.md enforcement)
# ============================================================================
# These replace the bash script's error handling pattern detection
# DENY: .unwrap() in production code (except test/bin with "// Safe" comments)
unwrap_used = "deny"
# DENY: .expect() in production code (except test/bin with "// Safe" comments)
expect_used = "deny"
# DENY: panic!() in production code (only acceptable in tests/bins)
panic = "deny"
# ============================================================================
# Allowed Exceptions (Per CLAUDE.md Policy)
# ============================================================================
# Type conversion casts - allowed when properly validated
cast_possible_truncation = "allow"
cast_sign_loss = "allow"
cast_precision_loss = "allow"
# Const fn suggestions - clippy suggests const for methods that can't actually be const
# (e.g., methods using .to_lowercase(), .map_or(), Utc::now(), etc.)
missing_const_for_fn = "allow"
# Structural patterns - validated separately
struct_excessive_bools = "allow"
# Long functions - allowed with mandatory documentation comment
# Script validates: "// Long function:" or "// Safe:" comment required
too_many_lines = "allow"
# Significant drop tightening - false positives with async lock guards
# The suggestions given are often syntactically invalid
significant_drop_tightening = "allow"
# ============================================================================
# Additional Code Quality Lints
# ============================================================================
# Catch common performance issues
clone_on_copy = "warn"
redundant_clone = "warn"
# Catch async anti-patterns
await_holding_lock = "warn"
# Catch string allocation inefficiencies
str_to_string = "deny"
# Module naming - allow repetition for clarity (e.g., error::ErrorKind)
module_name_repetitions = "allow"
# ============================================================================
# Rust Idiom Enforcement (Prevent AI-generated regressions)
# ============================================================================
# Enforce modern format string syntax: format!("{foo}") not format!("{}", foo)
uninlined_format_args = "warn"
# Warn on .map().unwrap_or() - should use map_or() or is_some_and() instead
map_unwrap_or = "warn"
# Enforce `use` imports over inline qualified paths (crate::foo::bar)
# Idiomatic Rust prefers imports at top of file for readability
absolute_paths = "deny"
# Disallow anyhow::Context methods - use structured ProviderError types instead
# Configuration in clippy.toml specifies which methods are banned
disallowed_methods = "deny"