use thiserror::Error;
#[derive(Debug, Error, PartialEq, Eq)]
#[error("secure randomness unavailable")]
pub struct RandomError;
#[derive(Debug, Error, PartialEq, Eq)]
pub enum KeyError {
#[error("no active HMAC key configured")]
MissingActiveKey,
#[error("HMAC key version not available")]
MissingKeyVersion,
#[error("HMAC key material is invalid")]
InvalidKeyMaterial,
}
#[derive(Debug, Error, PartialEq, Eq)]
pub enum PolicyError {
#[error("alphabet must contain at least 2 symbols")]
AlphabetTooSmall,
#[error("alphabet contains duplicate symbols")]
AlphabetNotUnique,
#[error("alphabet contains an unsupported (non-ASCII) symbol")]
AlphabetNotAscii,
#[error("code length {got} is below the secure minimum of {min}")]
LengthBelowMinimum {
got: usize,
min: usize,
},
#[error("code length must be non-zero")]
ZeroLength,
}
#[derive(Debug, Error, PartialEq, Eq)]
pub enum CodeInputError {
#[error("code input is empty")]
Empty,
#[error("code input exceeds maximum raw length")]
TooLongRaw,
#[error("normalized code length does not match policy")]
WrongLength,
#[error("code input contains unsupported characters")]
UnsupportedCharacters,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RedemptionFailReason {
InvalidFormat,
NotFound,
Expired,
Revoked,
AlreadyUsed,
RateLimited,
StoreUnavailable,
KeyFailure,
}
#[derive(Debug, Error, Clone, PartialEq, Eq)]
pub enum PublicRedemptionError {
#[error("invalid or expired code")]
InvalidOrExpired,
#[error("too many attempts — please wait and try again")]
RateLimited,
#[error("service temporarily unavailable")]
TemporarilyUnavailable,
}
impl PublicRedemptionError {
#[must_use]
pub fn from_reason(reason: &RedemptionFailReason) -> Self {
match reason {
RedemptionFailReason::InvalidFormat
| RedemptionFailReason::NotFound
| RedemptionFailReason::Expired
| RedemptionFailReason::Revoked
| RedemptionFailReason::AlreadyUsed => Self::InvalidOrExpired,
RedemptionFailReason::RateLimited => Self::RateLimited,
RedemptionFailReason::StoreUnavailable | RedemptionFailReason::KeyFailure => {
Self::TemporarilyUnavailable
}
}
}
}
#[derive(Debug, Error, Clone, PartialEq, Eq)]
pub enum PublicFormError {
#[error("form expired or invalid — please reload the page and try again")]
ExpiredOrInvalid,
#[error("service temporarily unavailable")]
TemporarilyUnavailable,
}
#[derive(Debug, Error, Clone, PartialEq, Eq)]
pub enum PublicSessionError {
#[error("session missing or expired — please sign in again")]
MissingOrExpired,
#[error("service temporarily unavailable")]
TemporarilyUnavailable,
}