Skip to main content

squigit_auth/
error.rs

1// Copyright 2026 a7mddra
2// SPDX-License-Identifier: Apache-2.0
3
4//! Error types for profile storage operations.
5
6use std::fmt;
7use std::io;
8use thiserror::Error;
9
10/// Result type alias for profile operations.
11pub type Result<T> = std::result::Result<T, ProfileError>;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum ByokErrorCode {
15    VaultUnavailable,
16    VaultLocked,
17    VaultDenied,
18    MasterKeyMissing,
19    CasBindingKeyMissing,
20    MalformedKeyStore,
21    InvalidCredential,
22    EncryptionFailed,
23}
24
25impl ByokErrorCode {
26    pub const fn as_str(self) -> &'static str {
27        match self {
28            Self::VaultUnavailable => "vault-unavailable",
29            Self::VaultLocked => "vault-locked",
30            Self::VaultDenied => "vault-denied",
31            Self::MasterKeyMissing => "master-key-missing",
32            Self::CasBindingKeyMissing => "cas-binding-key-missing",
33            Self::MalformedKeyStore => "malformed-key-store",
34            Self::InvalidCredential => "invalid-credential",
35            Self::EncryptionFailed => "encryption-failed",
36        }
37    }
38}
39
40impl fmt::Display for ByokErrorCode {
41    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
42        formatter.write_str(self.as_str())
43    }
44}
45
46/// Errors that can occur during profile operations.
47#[derive(Debug, Error)]
48pub enum ProfileError {
49    /// Profile with the given ID was not found.
50    #[error("Profile not found: {0}")]
51    ProfileNotFound(String),
52
53    /// API key provider name is unknown.
54    #[error("Invalid API key provider: {0}")]
55    InvalidProvider(String),
56
57    /// Google authentication is not configured.
58    #[error("{0}")]
59    MissingCredentials(String),
60
61    /// Authentication flow failed.
62    #[error("{0}")]
63    Auth(String),
64
65    /// Stable BYOK failure code plus a safe human-readable explanation.
66    #[error("{code}: {message}")]
67    Byok {
68        code: ByokErrorCode,
69        message: String,
70    },
71
72    /// IO error during file operations.
73    #[error("IO error: {0}")]
74    Io(#[from] io::Error),
75
76    /// JSON serialization/deserialization error.
77    #[error("JSON error: {0}")]
78    Json(#[from] serde_json::Error),
79
80    /// Profile/auth/key persistence failure from squigit-storage.
81    #[error("{0}")]
82    Storage(#[from] squigit_storage::StorageError),
83
84    /// HTTP or network failure during auth/avatar fetches.
85    #[error("Network error: {0}")]
86    Network(#[from] reqwest::Error),
87
88    /// Invalid URL encountered during auth flow construction/parsing.
89    #[error("URL error: {0}")]
90    Url(#[from] url::ParseError),
91}
92
93impl ProfileError {
94    pub fn byok(code: ByokErrorCode, message: impl Into<String>) -> Self {
95        Self::Byok {
96            code,
97            message: message.into(),
98        }
99    }
100}