use crate::types::{EdgeId, NodeId, PolicyBundleId, ScopeId, WitnessId};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum CoherenceError {
#[error("Substrate error: {0}")]
Substrate(#[from] SubstrateError),
#[error("Computation error: {0}")]
Computation(#[from] ComputationError),
#[error("Governance error: {0}")]
Governance(#[from] GovernanceError),
#[error("Execution error: {0}")]
Execution(#[from] ExecutionError),
#[error("Storage error: {0}")]
Storage(#[from] StorageError),
#[error("Configuration error: {0}")]
Config(String),
#[error("Internal error: {0}")]
Internal(String),
}
#[derive(Debug, Error)]
pub enum SubstrateError {
#[error("Node not found: {0}")]
NodeNotFound(NodeId),
#[error("Edge not found: {0}")]
EdgeNotFound(EdgeId),
#[error("Dimension mismatch: expected {expected}, got {actual}")]
DimensionMismatch {
expected: usize,
actual: usize,
},
#[error("Invalid restriction map: {0}")]
InvalidRestrictionMap(String),
#[error("Graph inconsistent: {0}")]
GraphInconsistent(String),
#[error("Node already exists: {0}")]
NodeAlreadyExists(NodeId),
#[error("Edge already exists: {0}")]
EdgeAlreadyExists(EdgeId),
#[error("Serialization error: {0}")]
Serialization(String),
}
#[derive(Debug, Error)]
pub enum ComputationError {
#[error("Residual computation failed for edge {edge}: {reason}")]
ResidualFailed {
edge: EdgeId,
reason: String,
},
#[error("Energy aggregation failed: {0}")]
AggregationFailed(String),
#[error("Spectral analysis failed: {0}")]
SpectralFailed(String),
#[error("Fingerprint mismatch: cached {cached}, current {current}")]
FingerprintMismatch {
cached: String,
current: String,
},
#[error("Numerical instability: {0}")]
NumericalInstability(String),
}
#[derive(Debug, Error)]
pub enum GovernanceError {
#[error("Policy bundle not found: {0}")]
PolicyNotFound(PolicyBundleId),
#[error("Policy bundle already activated: {0}")]
PolicyAlreadyActivated(PolicyBundleId),
#[error("Policy bundle not approved: {0}")]
PolicyNotApproved(PolicyBundleId),
#[error("Invalid signature from approver")]
InvalidSignature,
#[error("Insufficient approvals: required {required}, got {actual}")]
InsufficientApprovals {
required: usize,
actual: usize,
},
#[error("Witness chain broken: expected previous {expected:?}, got {actual:?}")]
WitnessChainBroken {
expected: Option<WitnessId>,
actual: Option<WitnessId>,
},
#[error("Witness not found: {0}")]
WitnessNotFound(WitnessId),
#[error("Witness integrity check failed: {0}")]
WitnessIntegrityFailed(WitnessId),
#[error("Invalid threshold configuration: {0}")]
InvalidThreshold(String),
#[error("Invalid scope pattern: {0}")]
InvalidScopePattern(String),
}
#[derive(Debug, Error)]
pub enum ExecutionError {
#[error("Action denied: {reason} (witness: {witness_id})")]
Denied {
witness_id: WitnessId,
reason: String,
},
#[error("Escalation required to lane {lane}: {reason}")]
EscalationRequired {
lane: u8,
reason: String,
},
#[error("Action execution failed: {0}")]
ActionFailed(String),
#[error("No policy bundle configured for scope: {0}")]
NoPolicyConfigured(ScopeId),
#[error("Policy bundle expired: {0}")]
PolicyExpired(PolicyBundleId),
#[error("Escalation timeout after {timeout_ms}ms")]
EscalationTimeout {
timeout_ms: u64,
},
#[error("Human review required but not available")]
HumanReviewUnavailable,
}
#[derive(Debug, Error)]
pub enum StorageError {
#[error("Database connection failed: {0}")]
ConnectionFailed(String),
#[error("Query failed: {0}")]
QueryFailed(String),
#[error("Transaction failed: {0}")]
TransactionFailed(String),
#[error("Record not found: {entity_type} with id {id}")]
NotFound {
entity_type: String,
id: String,
},
#[error("Duplicate key: {0}")]
DuplicateKey(String),
#[error("Serialization failed: {0}")]
SerializationFailed(String),
#[error("Deserialization failed: {0}")]
DeserializationFailed(String),
#[error("Event log error: {0}")]
EventLogError(String),
#[error("Replay failed at sequence {sequence}: {reason}")]
ReplayFailed {
sequence: u64,
reason: String,
},
}
pub type Result<T> = std::result::Result<T, CoherenceError>;
pub type SubstrateResult<T> = std::result::Result<T, SubstrateError>;
pub type ComputationResult<T> = std::result::Result<T, ComputationError>;
pub type GovernanceResult<T> = std::result::Result<T, GovernanceError>;
pub type ExecutionResult<T> = std::result::Result<T, ExecutionError>;
pub type StorageResult<T> = std::result::Result<T, StorageError>;
impl From<bincode::error::EncodeError> for SubstrateError {
fn from(e: bincode::error::EncodeError) -> Self {
Self::Serialization(e.to_string())
}
}
impl From<bincode::error::DecodeError> for SubstrateError {
fn from(e: bincode::error::DecodeError) -> Self {
Self::Serialization(e.to_string())
}
}
impl From<serde_json::Error> for StorageError {
fn from(e: serde_json::Error) -> Self {
Self::SerializationFailed(e.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = SubstrateError::DimensionMismatch {
expected: 64,
actual: 32,
};
assert!(err.to_string().contains("64"));
assert!(err.to_string().contains("32"));
}
#[test]
fn test_error_conversion() {
let substrate_err = SubstrateError::NodeNotFound(NodeId::new());
let coherence_err: CoherenceError = substrate_err.into();
assert!(matches!(coherence_err, CoherenceError::Substrate(_)));
}
}