Skip to main content

derec_library/protocol/
error.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 DeRec Alliance. All rights reserved.
3
4use super::SecretKind;
5use crate::types::ChannelId;
6
7/// Error returned by [`DeRecProtocol::process`](super::DeRecProtocol::process).
8///
9/// Wraps the underlying [`crate::Error`] with the `channel_id` extracted from
10/// the inbound message envelope, so consumers always know which channel
11/// produced the error.
12///
13/// `channel_id` is `None` only when the envelope itself could not be decoded
14/// (i.e. the raw bytes are not a valid protobuf `DeRecMessage`).
15#[derive(Debug, thiserror::Error)]
16#[error("{source}")]
17pub struct ProcessError {
18    /// The channel that produced the error, if the envelope was decodable.
19    pub channel_id: Option<ChannelId>,
20    /// The underlying error.
21    #[source]
22    pub source: crate::Error,
23}
24
25impl ProcessError {
26    /// Convenience: extract `(status, memo)` if the underlying error is a
27    /// `NonOkStatus` from any primitive.
28    pub fn as_non_ok_status(&self) -> Option<(i32, &str)> {
29        self.source.as_non_ok_status()
30    }
31}
32
33/// Errors produced by [`DeRecSecretStore`](super::DeRecSecretStore) implementations.
34///
35/// Individual Verifiable Secret Sharing shares are information-theoretically
36/// secure, so "secret" here refers only to [`SharedKey`](crate::types::SharedKey) and
37/// [`PairingKeyMaterial`](super::PairingKeyMaterial)
38/// — the two kinds of data stored in this trait.
39#[derive(Debug, thiserror::Error)]
40#[non_exhaustive]
41pub enum SecretStoreError {
42    /// An I/O or serialization error in the underlying storage backend.
43    ///
44    /// Used when the implementation cannot categorise the failure more
45    /// precisely (e.g., a file-system error, an SQLite constraint, or a
46    /// serialization failure).
47    ///
48    /// The original error is preserved as the `source` so that callers can
49    /// inspect the full error chain via [`std::error::Error::source`].
50    #[error("secret store backend error")]
51    Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
52
53    /// Returned by [`super::DeRecSecretStore::load_many`] when one or more
54    /// requested channels have no stored secret of the requested
55    /// [`SecretKind`] and the caller requested
56    /// [`super::MissingPolicy::Fail`].
57    ///
58    /// `channel_ids` carries the raw u64 ids of channels that came back empty;
59    /// the protocol orchestrator logs them at `error!` level and surfaces
60    /// the same list to consumers.
61    #[error("secret store: missing {kind:?} entries for channel(s): {channel_ids:?}")]
62    MissingEntries {
63        kind: SecretKind,
64        channel_ids: Vec<u64>,
65    },
66}
67
68/// Errors produced by [`DeRecChannelStore`](super::DeRecChannelStore) implementations.
69#[derive(Debug, thiserror::Error)]
70#[non_exhaustive]
71pub enum ChannelStoreError {
72    /// A channel with the given `channel_id` already exists.
73    #[error("channel already exists for {channel_id}")]
74    AlreadyExists { channel_id: u64 },
75
76    /// No channel was found for the given `channel_id`.
77    #[error("channel not found for {channel_id}")]
78    NotFound { channel_id: u64 },
79
80    /// An I/O or serialization error in the underlying storage backend.
81    #[error("channel store backend error")]
82    Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
83}
84
85/// Errors produced by [`DeRecStateStore`](super::DeRecStateStore) implementations.
86///
87/// The state store holds in-flight orchestrator state (outstanding
88/// verification challenges, in-progress recovery accumulators, pending unpair
89/// acknowledgements) so that stateless or load-balanced deployments do not
90/// lose it across process restarts.
91#[derive(Debug, thiserror::Error)]
92#[non_exhaustive]
93pub enum StateStoreError {
94    /// An I/O or serialization error in the underlying storage backend.
95    ///
96    /// The original error is preserved as the `source` so that callers can
97    /// inspect the full error chain via [`std::error::Error::source`].
98    #[error("state store backend error")]
99    Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
100}
101
102/// Errors produced by [`DeRecShareStore`](super::DeRecShareStore) implementations.
103#[derive(Debug, thiserror::Error)]
104#[non_exhaustive]
105pub enum ShareStoreError {
106    /// A share for `(channel_id, version)` already exists.
107    ///
108    /// Returned by [`DeRecShareStore::save`](super::DeRecShareStore::save) when the
109    /// implementation enforces immutability of versioned share slots.  The protocol treats each
110    /// `(channel_id, version)` pair as write-once; overwriting a confirmed share
111    /// is a protocol violation.
112    #[error("share already exists for channel {channel_id} version {version}")]
113    AlreadyExists { channel_id: u64, version: u32 },
114
115    /// No share was found for `(channel_id, version)`.
116    ///
117    /// Implementations that prefer an explicit error over returning `Ok(None)`
118    /// may return this variant from [`DeRecShareStore::load`](super::DeRecShareStore::load).
119    #[error("share not found for channel {channel_id} version {version}")]
120    NotFound { channel_id: u64, version: u32 },
121
122    /// An I/O or serialization error in the underlying storage backend.
123    ///
124    /// The original error is preserved as the `source` so that callers can
125    /// inspect the full error chain via [`std::error::Error::source`].
126    #[error("share store backend error")]
127    Backend(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
128}