From 8a0193577b76ef2bf4524c94f6975945cb7ebe33 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Fri, 29 May 2026 20:19:26 -0700 Subject: [PATCH] style(server): cargo fmt + clippy fixes for v2 keystone (CI green) The Task 2/3/authz commits failed CI at the first gate (cargo fmt --all --check), which short-circuited before clippy/build/test ran. Verified on the build host (172.16.3.30): the v2 server compiles and all 18 tests pass; only 3 cosmetic issues blocked CI, all fixed here: - cargo fmt --all (whitespace, 3 files) - clippy unused_imports: drop ViewerClaims from auth/mod.rs re-export - clippy doc_overindented_list_items: de-indent one doc line in sessions.rs Testing Agent confirmed fmt + clippy -D warnings + build --release + test are all green with these applied. No logic changes. Co-Authored-By: Claude Opus 4.8 (1M context) --- server/src/api/sessions.rs | 29 +++++++++++++++++--------- server/src/auth/agent_keys.rs | 5 ++++- server/src/auth/mod.rs | 2 +- server/src/relay/mod.rs | 39 ++++++++++++++++++++--------------- 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/server/src/api/sessions.rs b/server/src/api/sessions.rs index c676e94..af58f10 100644 --- a/server/src/api/sessions.rs +++ b/server/src/api/sessions.rs @@ -16,7 +16,7 @@ //! → a CONTROL token (input is forwarded to the agent). //! - else the `view` permission (see [`SESSION_VIEW_PERMISSION`]) //! → a VIEW-ONLY token (the relay refuses to forward this viewer's input; -//! video still streams). +//! video still streams). //! - else → 403 (standard envelope). //! //! This is why the gate is no longer a single `view` check: `view` is held by @@ -95,8 +95,13 @@ pub async fn mint_viewer_token( State(state): State, Path(id): Path, ) -> ApiResult> { - let session_id = Uuid::parse_str(&id) - .map_err(|_| err(StatusCode::BAD_REQUEST, "INVALID_SESSION_ID", "Invalid session ID"))?; + let session_id = Uuid::parse_str(&id).map_err(|_| { + err( + StatusCode::BAD_REQUEST, + "INVALID_SESSION_ID", + "Invalid session ID", + ) + })?; // TIERED AUTHORIZATION GATE (closes audit CRITICAL #1 — authz-strength split). // Authentication alone is not enough, and a single `view` check is too coarse @@ -127,13 +132,17 @@ pub async fn mint_viewer_token( // The session must exist (live session manager is the // source of truth for joinable sessions, matching GET /api/sessions/:id). - let session = state.sessions.get_session(session_id).await.ok_or_else(|| { - err( - StatusCode::NOT_FOUND, - "SESSION_NOT_FOUND", - "Session not found", - ) - })?; + let session = state + .sessions + .get_session(session_id) + .await + .ok_or_else(|| { + err( + StatusCode::NOT_FOUND, + "SESSION_NOT_FOUND", + "Session not found", + ) + })?; // Resolve tenancy (Phase-1: always the default tenant). Carried in the // claim so the WS and Phase-4 isolation can enforce it. diff --git a/server/src/auth/agent_keys.rs b/server/src/auth/agent_keys.rs index 4e93440..50ec50e 100644 --- a/server/src/auth/agent_keys.rs +++ b/server/src/auth/agent_keys.rs @@ -111,7 +111,10 @@ mod tests { let key = generate_agent_key(); assert!(key.starts_with(AGENT_KEY_PREFIX)); // prefix + 32 bytes * 2 hex chars - assert_eq!(key.len(), AGENT_KEY_PREFIX.len() + AGENT_KEY_RANDOM_BYTES * 2); + assert_eq!( + key.len(), + AGENT_KEY_PREFIX.len() + AGENT_KEY_RANDOM_BYTES * 2 + ); } #[test] diff --git a/server/src/auth/mod.rs b/server/src/auth/mod.rs index 7b6351e..950cfb3 100644 --- a/server/src/auth/mod.rs +++ b/server/src/auth/mod.rs @@ -8,7 +8,7 @@ pub mod jwt; pub mod password; pub mod token_blacklist; -pub use jwt::{Claims, JwtConfig, ViewerAccess, ViewerClaims}; +pub use jwt::{Claims, JwtConfig, ViewerAccess}; pub use password::{generate_random_password, hash_password, verify_password}; pub use token_blacklist::TokenBlacklist; diff --git a/server/src/relay/mod.rs b/server/src/relay/mod.rs index 71504df..02ee9a2 100644 --- a/server/src/relay/mod.rs +++ b/server/src/relay/mod.rs @@ -338,16 +338,18 @@ async fn validate_agent_api_key(state: &AppState, api_key: &str) -> AgentKeyAuth crate::auth::agent_keys::verify_agent_key(db.pool(), api_key).await { // Resolve the trusted identity from the authenticated key's machine. - let trusted_agent_id = match db::machines::get_machine_by_id(db.pool(), machine_id) - .await - { - Ok(Some(machine)) => Some(machine.agent_id), - Ok(None) => None, - Err(e) => { - tracing::error!("Failed to resolve machine for authenticated agent key: {}", e); - None - } - }; + let trusted_agent_id = + match db::machines::get_machine_by_id(db.pool(), machine_id).await { + Ok(Some(machine)) => Some(machine.agent_id), + Ok(None) => None, + Err(e) => { + tracing::error!( + "Failed to resolve machine for authenticated agent key: {}", + e + ); + None + } + }; return AgentKeyAuth::PerAgentKey(trusted_agent_id); } } @@ -403,13 +405,16 @@ pub async fn viewer_ws_handler( // 1. Signature + expiry + `purpose == "viewer"`. A login JWT fails this // (wrong claim shape / no `purpose`), so login tokens are no longer // accepted on the viewer plane. - let claims = state.jwt_config.validate_viewer_token(&token).map_err(|e| { - warn!( - "Viewer connection rejected from {}: invalid viewer token: {}", - client_ip, e - ); - StatusCode::UNAUTHORIZED - })?; + let claims = state + .jwt_config + .validate_viewer_token(&token) + .map_err(|e| { + warn!( + "Viewer connection rejected from {}: invalid viewer token: {}", + client_ip, e + ); + StatusCode::UNAUTHORIZED + })?; // 2. Revocation check on the WS plane (CRITICAL #2): a logged-out / revoked // token must not grant live remote control even before natural expiry.