use super::Severity;
use thiserror::Error;
#[derive(Error, Debug, PartialEq, Eq)]
pub enum GovernanceError {
#[error("ROOT_PUBLIC_KEY_HEX is not configured. This is a fatal error.")]
MissingRootKey,
#[error("Key length mismatch")]
KeyLengthMismatch,
#[error("Governance action too old, replay rejected")]
StaleProposal,
#[error("Timelock has not expired yet")]
TimelockNotExpired,
#[error("Target hash is not a pending timelock or was vetoed")]
NotPendingOrVetoed,
#[error("Governance is disabled in permissionless mode")]
GovernanceDisabled,
#[error("Insufficient valid signatures")]
InsufficientSignatures,
#[error("Premium name grants must be exactly 1 character long")]
InvalidPremiumNameLength,
#[error("Infrastructure name grants must target a valid Category 2 infrastructure name")]
InvalidInfrastructureName,
}
impl GovernanceError {
pub fn code(&self) -> &'static str {
match self {
Self::MissingRootKey => "KIN-GOV-001",
Self::GovernanceDisabled => "KIN-GOV-002",
Self::KeyLengthMismatch => "KIN-GOV-003",
Self::StaleProposal => "KIN-GOV-004",
Self::TimelockNotExpired => "KIN-GOV-005",
Self::NotPendingOrVetoed => "KIN-GOV-007",
Self::InsufficientSignatures => "KIN-GOV-016",
Self::InvalidPremiumNameLength => "KIN-GOV-019",
Self::InvalidInfrastructureName => "KIN-GOV-020",
}
}
pub fn error_type_uri(&self) -> String {
format!("{}/errors/{}", crate::constants::DOCS_URL, self.code())
}
pub fn severity(&self) -> Severity {
match self {
Self::MissingRootKey => Severity::Critical,
Self::StaleProposal | Self::TimelockNotExpired | Self::NotPendingOrVetoed => {
Severity::Info
}
Self::KeyLengthMismatch => Severity::Error,
Self::InsufficientSignatures
| Self::GovernanceDisabled
| Self::InvalidPremiumNameLength
| Self::InvalidInfrastructureName => Severity::Warning,
}
}
pub fn is_retryable(&self) -> bool {
matches!(
self,
Self::TimelockNotExpired | Self::InsufficientSignatures
)
}
pub fn user_message(&self) -> String {
match self {
Self::MissingRootKey => "The ROOT_PUBLIC_KEY_HEX environment variable is not set. This is a fatal configuration error.".to_string(),
Self::KeyLengthMismatch => "The provided cryptographic key length is invalid.".to_string(),
Self::StaleProposal => "The proposed governance action is too old and has been rejected to prevent replay attacks.".to_string(),
Self::TimelockNotExpired => "The governance action is still in its mandatory waiting period and cannot be executed yet.".to_string(),
Self::NotPendingOrVetoed => {
"The requested governance hash is not in a modifiable pending state.".to_string()
}
Self::GovernanceDisabled => {
"The network is operating in permissionless mode where governance actions are universally rejected.".to_string()
}
Self::InsufficientSignatures => {
"The message lacks the required cryptographic signatures to meet the council quorum threshold.".to_string()
}
Self::InvalidPremiumNameLength => "Premium names governed by this action must be exactly 1 character long.".to_string(),
Self::InvalidInfrastructureName => "Infrastructure names governed by this action must be valid Category 2 names.".to_string(),
}
}
}