Skip to main content

lemma/
limits.rs

1use crate::error::Error;
2
3pub const MAX_SPEC_NAME_LENGTH: usize = 128;
4pub const MAX_FACT_NAME_LENGTH: usize = 256;
5pub const MAX_RULE_NAME_LENGTH: usize = 256;
6pub const MAX_TYPE_NAME_LENGTH: usize = 256;
7
8/// Validate that a name does not exceed the given character limit.
9/// `kind` is a human-readable noun like "spec", "fact", "rule", or "type".
10pub fn check_max_length(name: &str, limit: usize, kind: &str) -> Result<(), Error> {
11    if name.len() > limit {
12        return Err(Error::ResourceLimitExceeded {
13            limit_name: format!("max_{kind}_name_length"),
14            limit_value: format!("{limit} characters"),
15            actual_value: format!("{} characters", name.len()),
16            suggestion: format!("Shorten the {kind} name to at most {limit} characters"),
17            spec_context: None,
18        });
19    }
20    Ok(())
21}
22
23/// Limits to prevent abuse and enable predictable resource usage
24///
25/// These limits protect against malicious inputs while being generous enough
26/// for all legitimate use cases.
27#[derive(Debug, Clone)]
28pub struct ResourceLimits {
29    /// Maximum file size in bytes
30    /// Real usage: ~5KB, Limit: 5MB (1000x)
31    pub max_file_size_bytes: usize,
32
33    /// Maximum expression nesting depth
34    /// Real usage: ~3 levels, Limit: 100 (30x+)
35    pub max_expression_depth: usize,
36
37    /// Maximum size of a single fact value in bytes
38    /// Real usage: ~100 bytes, Limit: 1KB (10x)
39    /// Enables server pre-allocation for zero-allocation evaluation
40    pub max_fact_value_bytes: usize,
41}
42
43impl Default for ResourceLimits {
44    fn default() -> Self {
45        Self {
46            max_file_size_bytes: 5 * 1024 * 1024, // 5 MB
47            max_expression_depth: 100,
48            max_fact_value_bytes: 1024, // 1 KB
49        }
50    }
51}