Skip to main content

fraiseql_core/security/
profiles.rs

1//! Security Profiles - v1.9.6 enforcement levels
2//!
3//! This module implements the v1.9.6 security profile system:
4//! - **STANDARD**: Basic security (rate limiting, audit logging)
5//! - **REGULATED**: Full compliance (HIPAA/SOC2 level with field masking, error redaction)
6//!
7//! ## Profile Levels
8//!
9//! ### STANDARD Profile
10//! - Rate limiting enabled
11//! - Audit logging of queries
12//! - Basic error messages visible
13//! - No field masking
14//! - Large responses allowed
15//!
16//! ### REGULATED Profile
17//! - All STANDARD features +
18//! - Detailed field-level audit logging
19//! - Sensitive field masking (PII, secrets)
20//! - Error detail reduction (no internal details)
21//! - Query logging for compliance audit trails
22//! - Response size limits (prevent data exfiltration)
23//! - Strict field filtering (only requested fields)
24//!
25//! ## Usage
26//!
27//! ```no_run
28//! use fraiseql_core::security::profiles::SecurityProfile;
29//!
30//! // Create a profile
31//! let profile = SecurityProfile::standard();
32//! assert!(profile.is_standard());
33//!
34//! let regulated = SecurityProfile::regulated();
35//! assert!(regulated.is_regulated());
36//! ```
37
38use std::fmt;
39
40use serde::{Deserialize, Serialize};
41
42/// Security profile configuration
43#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
44#[non_exhaustive]
45pub enum SecurityProfile {
46    /// STANDARD: Basic security (rate limit + audit)
47    #[default]
48    Standard,
49
50    /// REGULATED: Full security with compliance features (HIPAA/SOC2)
51    Regulated,
52}
53
54impl SecurityProfile {
55    /// Create STANDARD profile
56    #[must_use]
57    pub const fn standard() -> Self {
58        Self::Standard
59    }
60
61    /// Create REGULATED profile
62    #[must_use]
63    pub const fn regulated() -> Self {
64        Self::Regulated
65    }
66
67    /// Check if this is STANDARD profile
68    #[must_use]
69    pub const fn is_standard(&self) -> bool {
70        matches!(self, Self::Standard)
71    }
72
73    /// Check if this is REGULATED profile
74    #[must_use]
75    pub const fn is_regulated(&self) -> bool {
76        matches!(self, Self::Regulated)
77    }
78
79    /// Get profile name
80    #[must_use]
81    pub const fn name(&self) -> &'static str {
82        match self {
83            Self::Standard => "STANDARD",
84            Self::Regulated => "REGULATED",
85        }
86    }
87
88    /// Check if rate limiting is enabled for this profile
89    #[must_use]
90    pub const fn rate_limit_enabled(&self) -> bool {
91        true
92    }
93
94    /// Check if audit logging is enabled for this profile
95    #[must_use]
96    pub const fn audit_logging_enabled(&self) -> bool {
97        true
98    }
99
100    /// Check if field-level audit is enabled (REGULATED only)
101    #[must_use]
102    pub const fn audit_field_access(&self) -> bool {
103        matches!(self, Self::Regulated)
104    }
105
106    /// Check if sensitive field masking is enabled (REGULATED only)
107    #[must_use]
108    pub const fn sensitive_field_masking(&self) -> bool {
109        matches!(self, Self::Regulated)
110    }
111
112    /// Check if error detail reduction is enabled (REGULATED only)
113    #[must_use]
114    pub const fn error_detail_reduction(&self) -> bool {
115        matches!(self, Self::Regulated)
116    }
117
118    /// Check if query logging for compliance is enabled (REGULATED only)
119    #[must_use]
120    pub const fn query_logging_for_compliance(&self) -> bool {
121        matches!(self, Self::Regulated)
122    }
123
124    /// Check if response size limits are enforced (REGULATED only)
125    #[must_use]
126    pub const fn response_size_limits(&self) -> bool {
127        matches!(self, Self::Regulated)
128    }
129
130    /// Check if strict field filtering is enabled (REGULATED only)
131    #[must_use]
132    pub const fn field_filtering_strict(&self) -> bool {
133        matches!(self, Self::Regulated)
134    }
135
136    /// Get maximum response size for this profile (bytes)
137    #[must_use]
138    pub const fn max_response_size_bytes(&self) -> usize {
139        match self {
140            Self::Standard => usize::MAX, // No limit
141            Self::Regulated => 1_000_000, // 1MB for REGULATED
142        }
143    }
144
145    /// Get maximum query complexity for this profile
146    #[must_use]
147    pub const fn max_query_complexity(&self) -> usize {
148        match self {
149            Self::Standard => 100_000,
150            Self::Regulated => 50_000, // Stricter for REGULATED
151        }
152    }
153
154    /// Get maximum query depth for this profile
155    #[must_use]
156    pub const fn max_query_depth(&self) -> usize {
157        match self {
158            Self::Standard => 20,
159            Self::Regulated => 10, // Stricter for REGULATED
160        }
161    }
162
163    /// Get rate limit - requests per second per user
164    #[must_use]
165    pub const fn rate_limit_rps(&self) -> u32 {
166        match self {
167            Self::Standard => 100,
168            Self::Regulated => 10, // Stricter for REGULATED
169        }
170    }
171
172    /// Get enforcement level description
173    #[must_use]
174    pub const fn description(&self) -> &'static str {
175        match self {
176            Self::Standard => "Basic security with rate limiting and audit logging",
177            Self::Regulated => {
178                "Full compliance with field masking, error redaction, and strict limits"
179            },
180        }
181    }
182
183    /// Get all enforced features for this profile
184    #[must_use]
185    pub fn enforced_features(&self) -> Vec<&'static str> {
186        let mut features = vec!["Rate Limiting", "Audit Logging"];
187
188        if self.is_regulated() {
189            features.extend(vec![
190                "Field-Level Audit",
191                "Sensitive Field Masking",
192                "Error Detail Reduction",
193                "Query Logging for Compliance",
194                "Response Size Limits",
195                "Strict Field Filtering",
196            ]);
197        }
198
199        features
200    }
201}
202
203impl fmt::Display for SecurityProfile {
204    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205        write!(f, "{}", self.name())
206    }
207}