truthlinked_sdk/
error.rs

1use thiserror::Error;
2
3/// Errors that can occur when using the Truthlinked SDK
4/// 
5/// All error messages are designed to be safe for logging and do not leak
6/// sensitive information such as license keys or internal system details.
7/// 
8/// # Security Considerations
9/// - No credential information is included in error messages
10/// - Internal system details are not exposed
11/// - Error messages are safe to log and display to users
12/// - Stack traces do not contain sensitive information
13#[derive(Error, Debug)]
14pub enum TruthlinkedError {
15    /// Network-related errors (connection failures, timeouts, DNS resolution)
16    /// 
17    /// This error indicates a problem with network connectivity between the
18    /// client and the Truthlinked API. Common causes include:
19    /// - Internet connectivity issues
20    /// - DNS resolution failures
21    /// - Firewall blocking HTTPS traffic
22    /// - API server temporarily unavailable
23    #[error("Network error: {0}")]
24    Network(String),
25    
26    /// Authentication failed due to invalid or expired license key
27    /// 
28    /// This error occurs when:
29    /// - License key is malformed or invalid
30    /// - License key has expired
31    /// - License key signature verification fails
32    /// 
33    /// Resolution: Verify your license key and ensure it hasn't expired
34    #[error("Authentication failed")]
35    Unauthorized,
36    
37    /// Access denied due to insufficient license tier permissions
38    /// 
39    /// This error occurs when your license tier doesn't include access to
40    /// the requested operation. For example:
41    /// - Free tier attempting token exchange (requires Professional+)
42    /// - Professional tier attempting enforcement (requires Enterprise+)
43    /// 
44    /// Resolution: Upgrade your license tier or use a different endpoint
45    #[error("Access denied: insufficient tier permissions")]
46    Forbidden,
47    
48    /// Rate limit exceeded for your license tier
49    /// 
50    /// Each license tier has monthly request limits:
51    /// - Free: 1,000 requests/month
52    /// - Professional: 500,000 requests/month
53    /// - Enterprise: Unlimited
54    /// 
55    /// Resolution: Wait for the limit to reset or upgrade your tier
56    #[error("Rate limit exceeded: {0}")]
57    RateLimitExceeded(String),
58    
59    /// Request validation failed due to invalid parameters
60    /// 
61    /// This error indicates that the request parameters are malformed,
62    /// missing required fields, or contain invalid values.
63    /// 
64    /// Resolution: Check the API documentation and verify request parameters
65    #[error("Invalid request: {0}")]
66    InvalidRequest(String),
67    
68    /// Internal server error occurred
69    /// 
70    /// This indicates a problem on the Truthlinked API server side.
71    /// The issue has been logged and will be investigated.
72    /// 
73    /// Resolution: Retry the request after a brief delay
74    #[error("Server error")]
75    ServerError,
76    
77    /// Failed to serialize or deserialize request/response data
78    /// 
79    /// This error indicates a problem with JSON serialization/deserialization,
80    /// typically due to unexpected response format from the server.
81    #[error("Serialization error")]
82    SerializationError,
83    
84    /// Received an invalid or unexpected response from the server
85    /// 
86    /// This error occurs when the server returns a response that doesn't
87    /// match the expected format or contains invalid data.
88    #[error("Invalid response from server")]
89    InvalidResponse,
90    
91    /// License has expired and needs to be renewed
92    /// 
93    /// Your license key has passed its expiration date and is no longer valid.
94    /// 
95    /// Resolution: Contact support to renew your license
96    #[error("License expired")]
97    LicenseExpired,
98}
99
100impl From<reqwest::Error> for TruthlinkedError {
101    fn from(err: reqwest::Error) -> Self {
102        // Don't leak internal details
103        if err.is_timeout() {
104            TruthlinkedError::Network("Request timeout".to_string())
105        } else if err.is_connect() {
106            TruthlinkedError::Network("Connection failed".to_string())
107        } else {
108            TruthlinkedError::Network("Network error".to_string())
109        }
110    }
111}
112
113impl From<serde_json::Error> for TruthlinkedError {
114    fn from(_: serde_json::Error) -> Self {
115        // Don't leak JSON structure
116        TruthlinkedError::SerializationError
117    }
118}
119
120pub type Result<T> = std::result::Result<T, TruthlinkedError>;