zeph_config/
rate_limit.rs1use serde::{Deserialize, Serialize};
5
6fn default_shell_limit() -> usize {
7 30
8}
9
10fn default_web_limit() -> usize {
11 20
12}
13
14fn default_memory_limit() -> usize {
15 60
16}
17
18fn default_mcp_limit() -> usize {
19 40
20}
21
22fn default_other_limit() -> usize {
23 60
24}
25
26fn default_cooldown_secs() -> u64 {
27 30
28}
29
30fn default_rate_limit_enabled() -> bool {
31 true
32}
33
34#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
38pub struct RateLimitConfig {
39 #[serde(default = "default_rate_limit_enabled")]
41 pub enabled: bool,
42 #[serde(default = "default_shell_limit")]
44 pub shell_calls_per_minute: usize,
45 #[serde(default = "default_web_limit")]
47 pub web_calls_per_minute: usize,
48 #[serde(default = "default_memory_limit")]
50 pub memory_calls_per_minute: usize,
51 #[serde(default = "default_mcp_limit")]
53 pub mcp_calls_per_minute: usize,
54 #[serde(default = "default_other_limit")]
56 pub other_calls_per_minute: usize,
57 #[serde(default = "default_cooldown_secs")]
59 pub circuit_breaker_cooldown_secs: u64,
60}
61
62impl Default for RateLimitConfig {
63 fn default() -> Self {
64 Self {
65 enabled: true,
66 shell_calls_per_minute: default_shell_limit(),
67 web_calls_per_minute: default_web_limit(),
68 memory_calls_per_minute: default_memory_limit(),
69 mcp_calls_per_minute: default_mcp_limit(),
70 other_calls_per_minute: default_other_limit(),
71 circuit_breaker_cooldown_secs: default_cooldown_secs(),
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn default_is_enabled() {
82 assert!(RateLimitConfig::default().enabled);
83 }
84
85 #[test]
86 fn absent_section_defaults_to_enabled() {
87 let cfg: RateLimitConfig = toml::from_str("").unwrap();
88 assert!(
89 cfg.enabled,
90 "absent [security.rate_limit] must default to enabled = true"
91 );
92 }
93
94 #[test]
98 fn partial_section_still_defaults_to_enabled() {
99 let cfg: RateLimitConfig = toml::from_str("shell_calls_per_minute = 50").unwrap();
100 assert!(
101 cfg.enabled,
102 "partial [security.rate_limit] section must still default enabled = true"
103 );
104 assert_eq!(cfg.shell_calls_per_minute, 50);
105 }
106
107 #[test]
108 fn explicit_disabled_is_preserved() {
109 let cfg: RateLimitConfig = toml::from_str("enabled = false").unwrap();
110 assert!(!cfg.enabled, "explicit enabled = false must be preserved");
111 }
112
113 #[test]
114 fn explicit_disabled_with_partial_section_is_preserved() {
115 let cfg: RateLimitConfig =
116 toml::from_str("enabled = false\nshell_calls_per_minute = 50").unwrap();
117 assert!(!cfg.enabled);
118 assert_eq!(cfg.shell_calls_per_minute, 50);
119 }
120}