diff --git a/services/api_gateway/src/auth/interceptor.rs b/services/api_gateway/src/auth/interceptor.rs index 2ee84616a..cd795132d 100644 --- a/services/api_gateway/src/auth/interceptor.rs +++ b/services/api_gateway/src/auth/interceptor.rs @@ -204,7 +204,7 @@ impl LocalRevocationCache { let misses = self.misses.load(std::sync::atomic::Ordering::Relaxed); let total = hits .checked_add(misses) - .expect("Cache stats overflow: hits + misses exceeds u64"); + .unwrap_or(u64::MAX); let hit_rate = if total > 0 { let rate = (hits as f64 / total as f64) * 100.0; // f64 multiplication is safe, check for valid result diff --git a/services/api_gateway/src/auth/mtls/revocation.rs b/services/api_gateway/src/auth/mtls/revocation.rs index 5dd27f2a1..c74c22105 100644 --- a/services/api_gateway/src/auth/mtls/revocation.rs +++ b/services/api_gateway/src/auth/mtls/revocation.rs @@ -25,13 +25,19 @@ use x509_parser::{ }; // --- Prometheus Metrics --- +// SAFETY: Prometheus metric registration panics only if duplicate names exist, +// which is a fatal misconfiguration that should crash at startup. +#[allow(clippy::unwrap_used)] static OCSP_REQUESTS_TOTAL: Lazy = Lazy::new(|| register_int_counter!("ocsp_requests_total", "Total OCSP requests sent").unwrap()); +#[allow(clippy::unwrap_used)] static OCSP_CACHE_HITS: Lazy = Lazy::new(|| register_int_counter!("ocsp_cache_hits_total", "Total OCSP cache hits").unwrap()); +#[allow(clippy::unwrap_used)] static OCSP_CACHE_MISSES: Lazy = Lazy::new(|| { register_int_counter!("ocsp_cache_misses_total", "Total OCSP cache misses").unwrap() }); +#[allow(clippy::unwrap_used)] static OCSP_REVOKED_TOTAL: Lazy = Lazy::new(|| { register_int_counter!( "ocsp_revoked_certs_total", @@ -39,9 +45,11 @@ static OCSP_REVOKED_TOTAL: Lazy = Lazy::new(|| { ) .unwrap() }); +#[allow(clippy::unwrap_used)] static OCSP_REQUEST_FAILURES: Lazy = Lazy::new(|| { register_int_counter!("ocsp_request_failures_total", "Total failed OCSP requests").unwrap() }); +#[allow(clippy::unwrap_used)] static OCSP_RESPONSE_VALIDATION_FAILURES: Lazy = Lazy::new(|| { register_int_counter!( "ocsp_response_validation_failures_total", @@ -49,6 +57,7 @@ static OCSP_RESPONSE_VALIDATION_FAILURES: Lazy = Lazy::new(|| { ) .unwrap() }); +#[allow(clippy::unwrap_used)] static OCSP_REQUEST_LATENCY: Lazy = Lazy::new(|| { register_histogram!("ocsp_request_latency_seconds", "Latency of OCSP requests").unwrap() }); diff --git a/services/api_gateway/src/grpc/ml_trading_proxy.rs b/services/api_gateway/src/grpc/ml_trading_proxy.rs index 4a02ebf9a..19fbca048 100644 --- a/services/api_gateway/src/grpc/ml_trading_proxy.rs +++ b/services/api_gateway/src/grpc/ml_trading_proxy.rs @@ -75,10 +75,14 @@ impl MlTradingProxy { /// - Connection pooling managed by tonic::transport::Channel pub fn new(client: TradingServiceClient) -> Self { // Create rate limiter for predictions: 100 requests per minute per user + // SAFETY: NonZeroU32::new on positive constants always returns Some + #[allow(clippy::unwrap_used)] let quota_predictions = Quota::per_minute(NonZeroU32::new(100).unwrap()); let rate_limiter_predictions = Arc::new(GovernorRateLimiter::keyed(quota_predictions)); // Create rate limiter for performance queries: 20 requests per minute per user (expensive) + // SAFETY: NonZeroU32::new on positive constants always returns Some + #[allow(clippy::unwrap_used)] let quota_performance = Quota::per_minute(NonZeroU32::new(20).unwrap()); let rate_limiter_performance = Arc::new(GovernorRateLimiter::keyed(quota_performance)); diff --git a/services/api_gateway/src/lib.rs b/services/api_gateway/src/lib.rs index 021458ee5..d59aae27c 100644 --- a/services/api_gateway/src/lib.rs +++ b/services/api_gateway/src/lib.rs @@ -9,6 +9,9 @@ //! - Performance monitoring //! - Token bucket rate limiting with <50ns cache hits +#![deny(clippy::unwrap_used, clippy::expect_used)] +#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))] + // Include generated protobuf code FIRST (needed by other modules) pub mod foxhunt { pub mod tli { diff --git a/services/api_gateway/src/routing/rate_limiter.rs b/services/api_gateway/src/routing/rate_limiter.rs index d80e1bbca..4c7199da8 100644 --- a/services/api_gateway/src/routing/rate_limiter.rs +++ b/services/api_gateway/src/routing/rate_limiter.rs @@ -344,7 +344,7 @@ impl RateLimiter { let num_to_evict = self .max_cache_size .checked_div(10) - .expect("Division by zero in LRU eviction"); + .unwrap_or(1); // Collect entries with their last access time (lock-free iteration) let mut entries: Vec<_> = self diff --git a/services/backtesting_service/src/dbn_repository.rs b/services/backtesting_service/src/dbn_repository.rs index 9d5367372..e98d97ad8 100644 --- a/services/backtesting_service/src/dbn_repository.rs +++ b/services/backtesting_service/src/dbn_repository.rs @@ -330,13 +330,14 @@ impl DbnMarketDataRepository { return Err(anyhow::anyhow!("No data found for symbol: {}", symbol)); } + // SAFETY: bars is non-empty (validated by is_empty check above) let first = bars .first() - .expect("INVARIANT: bars is non-empty (validated above)") + .ok_or_else(|| anyhow::anyhow!("INVARIANT violated: bars is empty after check"))? .timestamp; let last = bars .last() - .expect("INVARIANT: bars is non-empty (validated above)") + .ok_or_else(|| anyhow::anyhow!("INVARIANT violated: bars is empty after check"))? .timestamp; debug!("Date range for {}: {} to {}", symbol, first, last); @@ -372,11 +373,11 @@ impl DbnMarketDataRepository { let bucket_start = bar .timestamp .with_minute((bar.timestamp.minute() / target_minutes) * target_minutes) - .unwrap() + .ok_or_else(|| anyhow::anyhow!("Invalid minute in timestamp resampling"))? .with_second(0) - .unwrap() + .ok_or_else(|| anyhow::anyhow!("Invalid second in timestamp resampling"))? .with_nanosecond(0) - .unwrap(); + .ok_or_else(|| anyhow::anyhow!("Invalid nanosecond in timestamp resampling"))?; // Start new bucket or add to existing match &mut current_bucket { @@ -391,11 +392,11 @@ impl DbnMarketDataRepository { .with_minute( (first_bar.timestamp.minute() / target_minutes) * target_minutes, ) - .unwrap() + .ok_or_else(|| anyhow::anyhow!("Invalid minute in timestamp resampling"))? .with_second(0) - .unwrap() + .ok_or_else(|| anyhow::anyhow!("Invalid second in timestamp resampling"))? .with_nanosecond(0) - .unwrap(); + .ok_or_else(|| anyhow::anyhow!("Invalid nanosecond in timestamp resampling"))?; if bucket_start == first_bucket_start { // Same bucket @@ -436,9 +437,10 @@ impl DbnMarketDataRepository { #[allow(clippy::indexing_slicing)] // Bounds checked above: !is_empty() let first = &bucket[0]; + // SAFETY: bucket is non-empty (validated by is_empty check above) let last = bucket .last() - .expect("INVARIANT: bucket is non-empty (validated above)"); + .ok_or_else(|| anyhow::anyhow!("INVARIANT violated: bucket is empty after check"))?; // Calculate OHLCV let open = first.open; diff --git a/services/backtesting_service/src/lib.rs b/services/backtesting_service/src/lib.rs index beda94061..a3e4b1f2f 100644 --- a/services/backtesting_service/src/lib.rs +++ b/services/backtesting_service/src/lib.rs @@ -4,8 +4,8 @@ //! for testing purposes. #![warn(missing_docs)] -#![allow(clippy::unwrap_used)] -#![allow(clippy::expect_used)] +#![deny(clippy::unwrap_used, clippy::expect_used)] +#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))] /// Performance analysis and metrics pub mod performance; diff --git a/services/backtesting_service/src/simple_metrics.rs b/services/backtesting_service/src/simple_metrics.rs index 1ec5ad9f0..c50cc294e 100644 --- a/services/backtesting_service/src/simple_metrics.rs +++ b/services/backtesting_service/src/simple_metrics.rs @@ -5,7 +5,11 @@ use once_cell::sync::Lazy; use prometheus::{register_counter, register_gauge, Counter, Gauge}; +// SAFETY: Prometheus metric registration panics only if duplicate names exist, +// which is a fatal misconfiguration that should crash at startup. + /// Service uptime in seconds +#[allow(clippy::expect_used)] pub static SERVICE_UPTIME: Lazy = Lazy::new(|| { register_gauge!( "backtesting_service_uptime_seconds", @@ -15,6 +19,7 @@ pub static SERVICE_UPTIME: Lazy = Lazy::new(|| { }); /// Total number of backtests started +#[allow(clippy::expect_used)] pub static BACKTESTS_STARTED: Lazy = Lazy::new(|| { register_counter!( "backtesting_backtests_started_total", @@ -24,6 +29,7 @@ pub static BACKTESTS_STARTED: Lazy = Lazy::new(|| { }); /// Total number of backtests completed +#[allow(clippy::expect_used)] pub static BACKTESTS_COMPLETED: Lazy = Lazy::new(|| { register_counter!( "backtesting_backtests_completed_total", @@ -35,6 +41,7 @@ pub static BACKTESTS_COMPLETED: Lazy = Lazy::new(|| { }); /// Total number of backtest errors +#[allow(clippy::expect_used)] pub static BACKTEST_ERRORS: Lazy = Lazy::new(|| { register_counter!( "backtesting_errors_total",