coven_replication/sync/store/membership/
mod.rs1use coven_keys::keys::KeyError;
7use coven_protocol::membership::MembershipConflict;
8use coven_protocol::objects::StorageError;
9use coven_protocol::objects::StoreObjectError;
10use coven_storage::CloudHomeJoinInfo;
11use serde::{Deserialize, Serialize};
12
13#[derive(Clone, Serialize, Deserialize, Debug)]
14#[serde(deny_unknown_fields)]
15pub struct MemberAdmission {
16 pub store_id: String,
17 pub store_name: String,
18 pub join_info: CloudHomeJoinInfo,
19 pub owner_pubkey: String,
20 pub wrapped_key: coven_protocol::wrapped_store_key::WrappedStoreKeyRef,
21 pub store_root: coven_protocol::store_commit::StoreRootRef,
22 pub membership_floor: coven_protocol::membership::MembershipFloor,
23}
24
25#[derive(Debug, thiserror::Error)]
33pub enum MembershipOpsError {
34 #[error("membership storage error: {0}")]
35 Storage(#[from] StorageError),
36 #[error("Store protocol object error: {0}")]
37 StoreObject(#[from] coven_protocol::objects::StoreObjectError),
38 #[error("membership database state error: {0}")]
39 Database(#[from] coven_database::DbError),
40 #[error("Store access failed: {0}")]
41 Store(#[from] crate::sync::store::StoreError),
42 #[error("{0}")]
43 Chain(#[from] AnchoredChainError),
44 #[error("{0}")]
45 Mutation(#[from] MembershipMutationError),
46 #[error(
50 "member removal committed the cloud key rotation, but this device could not \
51 adopt the rotated key locally: {source}; retry the same removal"
52 )]
53 RotationCommittedAdoptionFailed {
54 #[source]
55 source: KeyError,
56 },
57 #[error("cannot admit this device as a new member")]
58 SelfAdmission,
59 #[error("the identity is already a member with different role or provider account")]
60 ExistingMemberMismatch,
61 #[error("the existing member does not have exactly one current wrapped Store key")]
62 ExistingMemberKeyAuthority,
63 #[error(
67 "no membership chain to admit into: the store's founder entry is \
68 missing (it is established at store creation)"
69 )]
70 NoFounderChainForAdmission,
71 #[error("membership chain has no founder")]
72 ChainHasNoFounder,
73 #[error("membership has an unresolved semantic conflict: {0:?}")]
74 SemanticConflict(Box<MembershipConflict>),
75 #[error("sharing requires an encrypted cloud home")]
76 NotEncryptedHome,
77}
78
79mod mutation;
80
81#[derive(Debug, thiserror::Error)]
83pub enum AnchoredChainError {
84 #[error("membership storage unavailable while {operation}: {source}")]
85 StorageUnavailable {
86 operation: String,
87 #[source]
88 source: StorageError,
89 },
90 #[error("membership chain failed to load/validate: {0}")]
91 LoadFailed(String),
92 #[error("membership object: {0}")]
93 Object(#[from] StoreObjectError),
94 #[error("membership database: {0}")]
95 Database(#[from] coven_database::DbError),
96 #[error("membership protocol: {0}")]
97 Membership(#[from] coven_protocol::membership::MembershipError),
98 #[error("membership provider probe: {0}")]
99 ProviderProbe(#[from] coven_protocol::provider::ProviderProbeError),
100 #[error("membership floor failed validation: {0}")]
101 InvalidFloor(#[from] coven_protocol::membership::MembershipFloorError),
102 #[error("membership Store pull: {0}")]
103 StorePull(#[source] Box<crate::sync::store::StorePullError>),
104 #[error("chain founder {founder:?} is not the pinned owner {owner}")]
105 FounderMismatch {
106 founder: Option<String>,
107 owner: String,
108 },
109}
110
111impl From<crate::sync::store::StorePullError> for AnchoredChainError {
112 fn from(error: crate::sync::store::StorePullError) -> Self {
113 Self::StorePull(Box::new(error))
114 }
115}
116
117impl AnchoredChainError {
118 pub(crate) fn from_store_object(error: StoreObjectError) -> Self {
119 match error {
120 StoreObjectError::Storage(source @ StorageError::Storage(_))
121 | StoreObjectError::Storage(source @ StorageError::RotationPending(_)) => {
122 Self::StorageUnavailable {
123 operation: "discovering immutable membership objects".to_string(),
124 source,
125 }
126 }
127 error => Self::Object(error),
128 }
129 }
130}
131
132pub use mutation::MembershipMutationError;
133
134#[cfg(test)]
135mod tests;