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>;