use crate::diagnostics::ScoreLabel;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct ScanInput {
#[schemars(
description = "Absolute path to the Rust project directory to analyze. Must contain a Cargo.toml file."
)]
pub directory: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(
description = "Git branch name to diff against (e.g. 'main', 'develop'). When set, only files changed vs this branch are scanned. Omit to scan all files."
)]
pub diff: Option<String>,
#[serde(default = "default_mcp_offline")]
#[schemars(
description = "When true, cargo-audit runs with --no-fetch (no network access). Defaults to true in MCP mode for security."
)]
pub offline: bool,
#[serde(default)]
#[schemars(
description = "When true, ignores the project's rust-doctor.toml config file. Useful for untrusted projects."
)]
pub ignore_project_config: bool,
}
pub(super) const fn default_mcp_offline() -> bool {
true
}
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct ScoreInput {
#[schemars(
description = "Absolute path to the Rust project directory to score. Must contain a Cargo.toml file."
)]
pub directory: String,
#[serde(default = "default_mcp_offline")]
#[schemars(
description = "When true, cargo-audit runs with --no-fetch (no network access). Defaults to true in MCP mode."
)]
pub offline: bool,
#[serde(default)]
#[schemars(
description = "When true, ignores the project's rust-doctor.toml config file (so config cannot suppress security rules and inflate the score). Useful for untrusted projects. Aligned with the scan tool; defaults to false."
)]
pub ignore_project_config: bool,
}
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct ExplainRuleInput {
#[schemars(
description = "Rule identifier to explain. Accepts custom rule IDs (e.g. 'unwrap-in-production') or clippy lint names (e.g. 'clippy::expect_used'). Use list_rules to discover available IDs."
)]
pub rule: String,
}
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct DeepAuditArgs {
#[schemars(
description = "Absolute path to the Rust project directory to audit. Must contain a Cargo.toml file."
)]
pub directory: String,
}
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct HealthCheckArgs {
#[schemars(
description = "Absolute path to the Rust project directory to check. Must contain a Cargo.toml file."
)]
pub directory: String,
}
pub(super) const MAX_EXAMPLES_PER_GROUP: usize = 3;
#[derive(Serialize, JsonSchema)]
pub struct DiagnosticExample {
pub file_path: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub line: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub column: Option<u32>,
}
#[derive(Serialize, JsonSchema)]
pub struct DiagnosticGroup {
pub rule: String,
pub severity: String,
pub category: String,
pub count: usize,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub help: Option<String>,
pub examples: Vec<DiagnosticExample>,
}
#[derive(Serialize, JsonSchema)]
pub struct ScoreOutput {
pub score: u32,
pub score_label: ScoreLabel,
}