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}