1mod continuous;
25mod mutation;
26mod prioritize;
27mod rules;
28mod signal;
29mod source;
30
31pub use continuous::*;
32pub use mutation::*;
33pub use prioritize::*;
34pub use rules::*;
35pub use signal::*;
36pub use source::*;
37
38use serde::{Deserialize, Serialize};
39use thiserror::Error;
40
41#[derive(Error, Debug)]
43pub enum IntakeError {
44 #[error("Failed to parse webhook payload: {0}")]
45 ParseError(String),
46
47 #[error("Failed to extract signals: {0}")]
48 SignalExtractionError(String),
49
50 #[error("Failed to create mutation: {0}")]
51 MutationError(String),
52
53 #[error("Configuration error: {0}")]
54 ConfigError(String),
55
56 #[error("Storage error: {0}")]
57 StorageError(String),
58}
59
60pub type IntakeResult<T> = Result<T, IntakeError>;
62
63#[derive(Clone, Debug, Serialize, Deserialize)]
65pub struct IntakeConfig {
66 pub enabled: bool,
68
69 pub sources: Vec<IntakeSourceConfig>,
71
72 pub signal_extraction: SignalExtractionConfig,
74
75 pub rate_limit: RateLimitConfig,
77}
78
79impl Default for IntakeConfig {
80 fn default() -> Self {
81 Self {
82 enabled: true,
83 sources: vec![],
84 signal_extraction: SignalExtractionConfig::default(),
85 rate_limit: RateLimitConfig::default(),
86 }
87 }
88}
89
90#[derive(Clone, Debug, Serialize, Deserialize)]
92pub struct IntakeSourceConfig {
93 pub source_type: String,
95
96 pub enabled: bool,
98
99 pub config: serde_json::Value,
101}
102
103#[derive(Clone, Debug, Serialize, Deserialize)]
105pub struct SignalExtractionConfig {
106 pub min_confidence: f32,
108
109 pub max_signals: usize,
111
112 pub enable_pattern_learning: bool,
114}
115
116impl Default for SignalExtractionConfig {
117 fn default() -> Self {
118 Self {
119 min_confidence: 0.5,
120 max_signals: 10,
121 enable_pattern_learning: false,
122 }
123 }
124}
125
126#[derive(Clone, Debug, Serialize, Deserialize)]
128pub struct RateLimitConfig {
129 pub max_requests_per_minute: usize,
131
132 pub max_concurrent: usize,
134
135 pub backoff_seconds: u64,
137}
138
139impl Default for RateLimitConfig {
140 fn default() -> Self {
141 Self {
142 max_requests_per_minute: 60,
143 max_concurrent: 10,
144 backoff_seconds: 60,
145 }
146 }
147}
148
149pub fn generate_intake_id(prefix: &str) -> String {
151 let uuid = uuid::Uuid::new_v4();
152 format!("{}-{}", prefix, uuid)
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_generate_intake_id() {
161 let id = generate_intake_id("intake");
162 assert!(id.starts_with("intake-"));
163 }
164
165 #[test]
166 fn test_default_config() {
167 let config = IntakeConfig::default();
168 assert!(config.enabled);
169 assert!(config.sources.is_empty());
170 }
171}