1use crate::core::Capability;
4use thiserror::Error;
5
6pub use auths_crypto::AuthsErrorInfo;
7
8#[derive(Error, Debug)]
10pub enum AttestationError {
11 #[error("Issuer signature verification failed: {0}")]
13 IssuerSignatureFailed(String),
14
15 #[error("Device signature verification failed: {0}")]
17 DeviceSignatureFailed(String),
18
19 #[error("Attestation expired on {at}")]
21 AttestationExpired {
22 at: String,
24 },
25
26 #[error("Attestation revoked")]
28 AttestationRevoked,
29
30 #[error("Attestation timestamp {at} is in the future")]
32 TimestampInFuture {
33 at: String,
35 },
36
37 #[error("Missing required capability: required {required:?}, available {available:?}")]
39 MissingCapability {
40 required: Capability,
42 available: Vec<Capability>,
44 },
45
46 #[error("Signing failed: {0}")]
48 SigningError(String),
49
50 #[error("DID resolution failed: {0}")]
52 DidResolutionError(String),
53
54 #[error("Serialization error: {0}")]
56 SerializationError(String),
57
58 #[error("Invalid input: {0}")]
60 InvalidInput(String),
61
62 #[error("Crypto error: {0}")]
64 CryptoError(String),
65
66 #[error("Input too large: {0}")]
68 InputTooLarge(String),
69
70 #[error("Internal error: {0}")]
72 InternalError(String),
73
74 #[error("Organizational Attestation verification failed: {0}")]
76 OrgVerificationFailed(String),
77
78 #[error("Organizational Attestation expired")]
80 OrgAttestationExpired,
81
82 #[error("Organizational DID resolution failed: {0}")]
84 OrgDidResolutionFailed(String),
85
86 #[error("Bundle is {age_secs}s old (max {max_secs}s). Refresh with: auths id export-bundle")]
88 BundleExpired {
89 age_secs: u64,
91 max_secs: u64,
93 },
94
95 #[error("Attestation is {age_secs}s old (max {max_secs}s)")]
97 AttestationTooOld {
98 age_secs: u64,
100 max_secs: u64,
102 },
103}
104
105impl AuthsErrorInfo for AttestationError {
106 fn error_code(&self) -> &'static str {
107 match self {
108 Self::IssuerSignatureFailed(_) => "AUTHS-E2001",
109 Self::DeviceSignatureFailed(_) => "AUTHS-E2002",
110 Self::AttestationExpired { .. } => "AUTHS-E2003",
111 Self::AttestationRevoked => "AUTHS-E2004",
112 Self::TimestampInFuture { .. } => "AUTHS-E2005",
113 Self::MissingCapability { .. } => "AUTHS-E2006",
114 Self::SigningError(_) => "AUTHS-E2007",
115 Self::DidResolutionError(_) => "AUTHS-E2008",
116 Self::SerializationError(_) => "AUTHS-E2009",
117 Self::InputTooLarge(_) => "AUTHS-E2010",
118 Self::InvalidInput(_) => "AUTHS-E2011",
119 Self::CryptoError(_) => "AUTHS-E2012",
120 Self::InternalError(_) => "AUTHS-E2013",
121 Self::OrgVerificationFailed(_) => "AUTHS-E2014",
122 Self::OrgAttestationExpired => "AUTHS-E2015",
123 Self::OrgDidResolutionFailed(_) => "AUTHS-E2016",
124 Self::BundleExpired { .. } => "AUTHS-E2017",
125 Self::AttestationTooOld { .. } => "AUTHS-E2018",
126 }
127 }
128
129 fn suggestion(&self) -> Option<&'static str> {
130 match self {
131 Self::IssuerSignatureFailed(_) => {
132 Some("Verify the attestation was signed with the correct issuer key")
133 }
134 Self::DeviceSignatureFailed(_) => Some("Verify the device key matches the attestation"),
135 Self::AttestationExpired { .. } => Some("Request a new attestation from the issuer"),
136 Self::AttestationRevoked => {
137 Some("This device has been revoked; contact the identity admin")
138 }
139 Self::TimestampInFuture { .. } => Some("Check system clock synchronization"),
140 Self::MissingCapability { .. } => {
141 Some("Request an attestation with the required capability")
142 }
143 Self::DidResolutionError(_) => Some("Check that the DID is valid and resolvable"),
144 Self::OrgVerificationFailed(_) => {
145 Some("Verify organizational identity is properly configured")
146 }
147 Self::OrgAttestationExpired => {
148 Some("Request a new organizational attestation from the admin")
149 }
150 Self::OrgDidResolutionFailed(_) => {
151 Some("Check that the organization's DID is correctly configured")
152 }
153 Self::InputTooLarge(_) => {
155 Some("Reduce the size of the JSON input or split into smaller batches")
156 }
157 Self::BundleExpired { .. } => Some(
158 "Re-export the bundle: auths id export-bundle --alias <ALIAS> --output bundle.json --max-age-secs <SECS>",
159 ),
160 Self::AttestationTooOld { .. } => {
161 Some("Request a fresh attestation or increase the max_age threshold")
162 }
163 Self::SigningError(_) => {
164 Some("The cryptographic signing operation failed; verify key material is valid")
165 }
166 Self::SerializationError(_) => {
167 Some("Failed to serialize/deserialize attestation data; check JSON format")
168 }
169 Self::InvalidInput(_) => {
170 Some("Check the input parameters and ensure they match the expected format")
171 }
172 Self::CryptoError(_) => {
173 Some("A cryptographic operation failed; verify key material is valid")
174 }
175 Self::InternalError(_) => {
176 Some("An unexpected internal error occurred; please report this issue")
177 }
178 }
179 }
180}