Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions clients/rook/src/admin/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::admin::{
types::{
AccountView, AddPoolMemberRequest, AdminErrorResponse, AuditEventView,
CreateAccountRequest, CreatePoolRequest, CreateRouteRequest, HealthAccountView,
HealthSummaryView, ListAuditEventsQuery, OperatorRuntimeView, OperatorStatusView, PoolView,
RouteView, SettingsView, UpdateAccountRequest, UpdatePoolRequest, UpdateRouteRequest,
UpdateSettingsRequest, UsageAggregateView, UsageGroupView, UsageSummaryPeriod,
UsageSummaryView, UsageSummaryWindowView,
HealthSummaryView, ListAuditEventsQuery, OperationalStatusView, OperatorRuntimeView,
OperatorStatusView, PoolView, RouteView, SettingsView, UpdateAccountRequest,
UpdatePoolRequest, UpdateRouteRequest, UpdateSettingsRequest, UsageAggregateView,
UsageGroupView, UsageSummaryPeriod, UsageSummaryView, UsageSummaryWindowView,
},
AdminState,
};
Expand Down Expand Up @@ -276,6 +276,10 @@ pub async fn handle_operator_status(
metrics_enabled: true,
usage_accounting_enabled: true,
},
operational: OperationalStatusView {
debug_diagnostics: state.operational.debug_diagnostics,
redaction_baseline: "always_on",
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}),
))
}
Expand Down Expand Up @@ -962,6 +966,7 @@ mod tests {
observability: std::sync::Arc::new(
crate::observability::Observability::bootstrap(),
),
operational: crate::config::OperationalConfig::default(),
}),
req,
)
Expand Down
3 changes: 3 additions & 0 deletions clients/rook/src/admin/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod handlers;
pub mod types;

use crate::config::OperationalConfig;
use crate::health::StartupDependencyState;
use crate::observability::Observability;
use crate::registry::RookRegistry;
Expand All @@ -12,6 +13,7 @@ pub struct AdminState {
pub registry: RookRegistry,
pub startup: Arc<StartupDependencyState>,
pub observability: Arc<Observability>,
pub operational: OperationalConfig,
}

impl FromRef<AdminState> for Arc<StartupDependencyState> {
Expand Down Expand Up @@ -156,6 +158,7 @@ mod tests {
registry,
startup: std::sync::Arc::new(startup),
observability: std::sync::Arc::new(crate::observability::Observability::bootstrap()),
operational: crate::config::OperationalConfig::default(),
}
}

Expand Down
7 changes: 7 additions & 0 deletions clients/rook/src/admin/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ pub struct OperatorStatusView {
pub startup: crate::health::ReadinessResponse,
pub provider_health: HealthSummaryView,
pub runtime: OperatorRuntimeView,
pub operational: OperationalStatusView,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
Expand All @@ -159,6 +160,12 @@ pub struct OperatorRuntimeView {
pub usage_accounting_enabled: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct OperationalStatusView {
pub debug_diagnostics: bool,
pub redaction_baseline: &'static str,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RoutingPolicyView {
Expand Down
144 changes: 136 additions & 8 deletions clients/rook/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub struct RookConfig {
pub port: u16,
pub enable_tui: bool,
pub db_path: PathBuf,
pub operational: OperationalConfig,
pub inbound_auth: InboundAuthConfig,
pub transport: TransportConfig,
pub rate_limits: RateLimitConfig,
Expand All @@ -64,6 +65,7 @@ impl Default for RookConfig {
port: 4141,
enable_tui: false,
db_path: PathBuf::from("./rook.db"),
operational: OperationalConfig::default(),
inbound_auth: InboundAuthConfig::default(),
transport: TransportConfig::default(),
rate_limits: RateLimitConfig::default(),
Expand All @@ -80,13 +82,22 @@ pub struct PartialRookConfig {
pub port: Option<u16>,
pub enable_tui: Option<bool>,
pub db_path: Option<PathBuf>,
pub operational: Option<PartialOperationalConfig>,
pub inbound_auth: Option<PartialInboundAuthConfig>,

pub transport: Option<PartialTransportConfig>,
pub rate_limits: Option<PartialRateLimitConfig>,
pub idempotency: Option<PartialIdempotencyConfig>,
pub upstream_resilience: Option<PartialUpstreamResilienceConfig>,
}

#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct PartialOperationalConfig {
pub undercover: Option<bool>,
pub debug_diagnostics: Option<bool>,
}

#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct PartialInboundAuthConfig {
Expand Down Expand Up @@ -149,6 +160,13 @@ pub struct PartialIdempotencyConfig {
pub chat_completions: Option<PartialChatCompletionsIdempotencyConfig>,
}

#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct PartialChatCompletionsIdempotencyConfig {
pub enabled: Option<bool>,
pub replay_window_seconds: Option<u64>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UpstreamResilienceConfig {
pub max_buffered_attempts: usize,
Expand Down Expand Up @@ -209,13 +227,6 @@ pub struct PartialUpstreamResilienceConfig {
pub max_concurrent_upstream_requests: Option<usize>,
}

#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct PartialChatCompletionsIdempotencyConfig {
pub enabled: Option<bool>,
pub replay_window_seconds: Option<u64>,
}

#[derive(Debug, Clone, Default)]
pub struct CliRookConfigOverlay {
pub host: Option<String>,
Expand Down Expand Up @@ -331,6 +342,7 @@ impl RookConfig {
port: self.port,
enable_tui: self.enable_tui,
db_path: Some(self.db_path.display().to_string()),
operational: self.operational.clone(),
inbound_auth: self.inbound_auth.clone(),
transport: self.transport.clone(),
rate_limits: self.rate_limits.clone(),
Expand Down Expand Up @@ -367,6 +379,9 @@ impl PartialRookConfig {
if let Some(db_path) = self.db_path {
target.db_path = db_path;
}
if let Some(operational) = self.operational {
operational.apply_to(&mut target.operational);
}
if let Some(inbound_auth) = self.inbound_auth {
inbound_auth.apply_to(&mut target.inbound_auth);
}
Expand All @@ -385,6 +400,17 @@ impl PartialRookConfig {
}
}

impl PartialOperationalConfig {
fn apply_to(self, target: &mut OperationalConfig) {
if let Some(undercover) = self.undercover {
target.undercover = undercover;
}
if let Some(debug_diagnostics) = self.debug_diagnostics {
target.debug_diagnostics = debug_diagnostics;
}
}
}

impl PartialInboundAuthConfig {
fn apply_to(self, target: &mut InboundAuthConfig) {
if let Some(enabled) = self.enabled {
Expand Down Expand Up @@ -526,6 +552,7 @@ impl CliRookConfigOverlay {
port: self.port,
enable_tui: self.enable_tui,
db_path: self.db_path,
operational: None,
inbound_auth: self.inbound_auth,
transport: self.transport,
rate_limits: self.rate_limits,
Expand Down Expand Up @@ -556,6 +583,16 @@ fn parse_env_overlay(env: &HashMap<String, String>) -> Result<PartialRookConfig,
.map(|value| parse_bool_env("ROOK_ENABLE_TUI", value))
.transpose()?,
db_path: env.get("ROOK_DB_PATH").map(PathBuf::from),
operational: partial_if_any(PartialOperationalConfig {
undercover: env
.get("ROOK_UNDERCOVER")
.map(|value| parse_bool_env("ROOK_UNDERCOVER", value))
.transpose()?,
debug_diagnostics: env
.get("ROOK_DEBUG_DIAGNOSTICS")
.map(|value| parse_bool_env("ROOK_DEBUG_DIAGNOSTICS", value))
.transpose()?,
}),
inbound_auth: partial_if_any(PartialInboundAuthConfig {
enabled: env
.get("ROOK_INBOUND_AUTH_ENABLED")
Expand Down Expand Up @@ -725,6 +762,12 @@ trait PartialOverlay {
fn is_empty(&self) -> bool;
}

impl PartialOverlay for PartialOperationalConfig {
fn is_empty(&self) -> bool {
self.undercover.is_none() && self.debug_diagnostics.is_none()
}
}

impl PartialOverlay for PartialInboundAuthConfig {
fn is_empty(&self) -> bool {
self.enabled.is_none() && self.bearer_token.is_none()
Expand Down Expand Up @@ -809,13 +852,21 @@ pub struct RookConfigExportView {
pub port: u16,
pub enable_tui: bool,
pub db_path: String,
pub operational: OperationalExportView,
pub inbound_auth: InboundAuthExportView,
pub transport: TransportExportView,
pub rate_limits: RateLimitExportView,
pub idempotency: IdempotencyExportView,
pub upstream_resilience: UpstreamResilienceConfigExportView,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct OperationalExportView {
pub undercover: bool,
pub debug_diagnostics: bool,
pub redaction_baseline: &'static str,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct InboundAuthExportView {
pub enabled: bool,
Expand Down Expand Up @@ -931,7 +982,12 @@ impl RookConfigExportView {
host: config.host.clone(),
port: config.port,
enable_tui: config.enable_tui,
db_path: config.db_path.display().to_string(),
db_path: if config.operational.undercover {
"<redacted>".to_string()
} else {
config.db_path.display().to_string()
},
operational: OperationalExportView::from(&config.operational),
inbound_auth: InboundAuthExportView {
enabled: config.inbound_auth.enabled,
bearer_token: if config.inbound_auth.enabled {
Expand Down Expand Up @@ -998,6 +1054,33 @@ impl RookConfigExportView {
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OperationalConfig {
/// Keep secret/payload redaction enabled across diagnostics and operator surfaces.
pub undercover: bool,
/// Emit extra metadata-only diagnostics for agent/gateway debugging.
pub debug_diagnostics: bool,
}

impl Default for OperationalConfig {
fn default() -> Self {
Self {
undercover: false,
debug_diagnostics: false,
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

impl From<&OperationalConfig> for OperationalExportView {
fn from(config: &OperationalConfig) -> Self {
Self {
undercover: config.undercover,
debug_diagnostics: config.debug_diagnostics,
redaction_baseline: "always_on",
}
}
}

#[derive(Clone, PartialEq, Eq, Default)]
pub struct InboundAuthConfig {
pub enabled: bool,
Expand Down Expand Up @@ -1457,6 +1540,51 @@ mod tests {
);
}

#[test]
fn operational_config_defaults_to_undercover_disabled_and_debug_disabled() {
let config = super::RookConfig::default();

assert!(!config.operational.undercover);
assert!(!config.operational.debug_diagnostics);
}

#[test]
fn operational_config_loads_from_file_and_env() {
let from_file = super::RookConfig::from_toml_str(
r#"
[operational]
undercover = false
debug_diagnostics = true
"#,
)
.expect("operational config should parse");
assert!(!from_file.operational.undercover);
assert!(from_file.operational.debug_diagnostics);

let env = std::collections::HashMap::from([
("ROOK_UNDERCOVER".to_string(), "true".to_string()),
("ROOK_DEBUG_DIAGNOSTICS".to_string(), "false".to_string()),
]);
let from_env = super::RookConfig::from_sources(Some("[operational]\nundercover = false\ndebug_diagnostics = true\n"), &env)
.expect("env operational overrides should parse");

assert!(from_env.operational.undercover);
assert!(!from_env.operational.debug_diagnostics);
}

#[test]
fn config_export_view_includes_operational_controls_without_disabling_redaction_baseline() {
let mut config = super::RookConfig::default();
config.operational.undercover = false;
config.operational.debug_diagnostics = true;

let view = super::RookConfigExportView::from_config(&config);

assert!(!view.operational.undercover);
assert!(view.operational.debug_diagnostics);
assert_eq!(view.operational.redaction_baseline, "always_on");
}

#[test]
fn config_export_view_includes_upstream_resilience() {
let mut config = super::RookConfig::default();
Expand Down
Loading
Loading