peat_protocol/storage/capabilities.rs
1//! Storage backend capability traits
2//!
3//! This module defines **optional capabilities** that complete storage backends may provide.
4//!
5//! # What is a Backend?
6//!
7//! A **backend is a complete, integrated solution** for storage, synchronization, and persistence:
8//!
9//! - **AutomergeIrohBackend**: Automerge CRDTs + RocksDB persistence + Iroh QUIC + custom mesh (ADR-017)
10//! - **SimpleBackend**: RocksDB only (no CRDT, no sync, just local K/V storage)
11//!
12//! Backends are **not** individual components like "just Automerge" or "just Iroh". Each backend
13//! integrates multiple technologies into a cohesive solution.
14//!
15//! # Architecture Philosophy
16//!
17//! Rather than forcing all backends into a one-size-fits-all trait, we use
18//! **capability traits** to expose what each complete backend can do:
19//!
20//! ```text
21//! ┌─────────────────────────────────────────────────────────┐
22//! │ Peat Protocol Business Logic │
23//! │ (Uses StorageBackend + optional capabilities) │
24//! └─────────────────┬───────────────────────────────────────┘
25//! │
26//! ┌─────────────────▼───────────────────────────────────────┐
27//! │ StorageBackend (required for all backends) │
28//! │ • collection() - Basic CRUD via Vec<u8> │
29//! │ • flush() - Persistence guarantee │
30//! └─────────────────┬───────────────────────────────────────┘
31//! │
32//! ┌──────────┴──────────────┐
33//! ▼ ▼
34//! ┌─────────────────────┐ ┌──────────┐
35//! │ AutomergeIrohBackend│ │ Simple │
36//! │ =================== │ │ Backend │
37//! │ • Automerge CRDTs │ │ ======== │
38//! │ • RocksDB persist │ │ • RocksDB│
39//! │ • Iroh QUIC │ │ only │
40//! │ • Custom mesh │ │ │
41//! │ (ADR-017) │ │ │
42//! │ │ │ │
43//! │ + CrdtCapable │ │ │
44//! │ + SyncCapable │ │ │
45//! └─────────────────────┘ └──────────┘
46//! (one complete OSS (minimal
47//! stack, not separate backend)
48//! pieces)
49//! ```
50//!
51//! # Backend Comparison
52//!
53//! | Backend | Components | CRDT | Sync | License | Use Case |
54//! |------------------------|-------------------------------------|------|------|------------|--------------------------|
55//! | **AutomergeIrohBackend**| Automerge + RocksDB + Iroh + mesh | ✅ | ✅ | MIT/Apache | OSS, self-hosted |
56//! | **SimpleBackend** | RocksDB only | ❌ | ❌ | Apache 2.0 | Testing, local storage |
57//!
58//! # Capability Traits
59//!
60//! ## CrdtCapable - Field-Level Conflict Resolution
61//!
62//! Backends that implement `CrdtCapable` can store structured data and provide
63//! CRDT-based conflict resolution at the field level, not just document level.
64//!
65//! **Benefits:**
66//! - OR-Set semantics for arrays (concurrent additions merge correctly)
67//! - LWW-Register for scalar fields (timestamp-based resolution)
68//! - Delta sync (only changed fields transmitted)
69//! - 50x+ bandwidth reduction vs. full document sync
70//!
71//! **Requirements:**
72//! - Protobuf messages must have `#[derive(Serialize, Deserialize)]`
73//! - Backend must support structured storage (Automerge document)
74//!
75//! **Example (AutomergeIrohBackend):**
76//! ```ignore
77//! use peat_protocol::storage::{AutomergeIrohBackend, CrdtCapable};
78//!
79//! let backend = AutomergeIrohBackend::new(config);
80//! let squads: Arc<dyn TypedCollection<SquadSummary>> =
81//! backend.typed_collection("squads");
82//! squads.upsert("squad-1", &summary)?;
83//! // → Automerge stores as CRDT document, persists to RocksDB, syncs via Iroh
84//! ```
85//!
86//! ## SyncCapable - Built-in Replication
87//!
88//! Backends that implement `SyncCapable` have built-in P2P synchronization.
89//!
90//! **AutomergeIrohBackend**: Integrated with Iroh QUIC transport + custom mesh (ADR-017)
91//!
92//! # Decision Guide
93//!
94//! ## When to use basic `StorageBackend` interface:
95//!
96//! - ✅ Backend-agnostic code (must work with any backend)
97//! - ✅ Testing with mocks
98//! - ✅ CRDT benefits not critical
99//! - ✅ Simple binary data storage
100//!
101//! ## When to use `CrdtCapable` interface:
102//!
103//! - ✅ Field-level conflict resolution needed
104//! - ✅ Delta sync bandwidth optimization critical
105//! - ✅ Type safety at compile time desired
106//! - ✅ Willing to add serde derives to protobuf messages
107//!
108//! ## When to use `SyncCapable` interface:
109//!
110//! - ✅ Need to control sync lifecycle (start/stop)
111//! - ✅ Need sync statistics and monitoring
112//!
113//! # Open Source Path
114//!
115//! Peat Protocol provides a **fully open-source implementation** using:
116//!
117//! ```text
118//! ┌──────────────────────────────────────────────────────────┐
119//! │ Peat Protocol (Apache 2.0) │
120//! ├──────────────────────────────────────────────────────────┤
121//! │ AutomergeIrohBackend (complete OSS backend) │
122//! │ Components: │
123//! │ • Automerge (MIT) - CRDT engine │
124//! │ • RocksDB (Apache 2.0) - Persistence layer │
125//! │ • Iroh (Apache 2.0/MIT) - QUIC transport │
126//! │ • Custom P2P mesh (ADR-017) - Discovery & topology │
127//! │ │
128//! │ Capabilities: │
129//! │ └─ StorageBackend: Yes (required) │
130//! │ └─ CrdtCapable: Yes (via Automerge CRDTs) │
131//! │ └─ SyncCapable: Yes (via Iroh + custom mesh) │
132//! └──────────────────────────────────────────────────────────┘
133//! ```
134//!
135//! This ensures:
136//! - ✅ No vendor lock-in
137//! - ✅ Full auditability
138//! - ✅ Military/government deployment sovereignty
139//! - ✅ Community contributions and forks
140//!
141//! # Future Capabilities
142//!
143//! Additional capability traits may be added:
144//! - `QueryCapable` - Advanced query DSLs
145//! - `IndexCapable` - Secondary indexes
146//! - `TransactionCapable` - Multi-document ACID transactions
147//! - `EncryptionCapable` - At-rest encryption
148
149use crate::command::CommandStorage;
150use crate::hierarchy::SummaryStorage;
151use anyhow::Result;
152use prost::Message;
153use serde::{de::DeserializeOwned, Serialize};
154use std::sync::Arc;
155
156/// Typed collection trait for CRDT-optimized storage
157///
158/// Backends that implement `CrdtCapable` provide this trait to enable
159/// field-level conflict resolution via CRDT semantics.
160///
161/// # Type Parameters
162///
163/// * `M` - Protobuf message type with serde support
164///
165/// # CRDT Semantics
166///
167/// Different field types get different CRDT semantics:
168/// - **Arrays**: OR-Set (observed-remove set) - concurrent additions merge
169/// - **Scalars**: LWW-Register (last-write-wins) - timestamp-based resolution
170/// - **Nested objects**: Recursive application of above rules
171///
172/// # Example
173///
174/// ```ignore
175/// use peat_protocol::storage::{CrdtCapable, TypedCollection};
176/// use peat_schema::hierarchy::v1::SquadSummary;
177///
178/// let backend = AutomergeIrohBackend::new(config);
179/// let squads: Arc<dyn TypedCollection<SquadSummary>> =
180/// backend.typed_collection("squads");
181///
182/// // Field-level updates
183/// let mut summary = squads.get("squad-1")?.unwrap();
184/// summary.member_ids.push("node-4".to_string()); // OR-Set addition
185/// squads.upsert("squad-1", &summary)?;
186/// // → Only member_ids field is transmitted, not entire document
187/// ```
188pub trait TypedCollection<M>: Send + Sync
189where
190 M: Message + Serialize + DeserializeOwned + Default + Clone,
191{
192 /// Insert or update a typed document with CRDT merging
193 ///
194 /// Backends convert the message to their CRDT format:
195 /// - Automerge: `message` → Automerge document
196 fn upsert(&self, doc_id: &str, message: &M) -> Result<()>;
197
198 /// Get a typed document by ID
199 fn get(&self, doc_id: &str) -> Result<Option<M>>;
200
201 /// Delete a typed document by ID
202 fn delete(&self, doc_id: &str) -> Result<()>;
203
204 /// Scan all typed documents in the collection
205 fn scan(&self) -> Result<Vec<(String, M)>>;
206
207 /// Find typed documents matching a predicate
208 fn find(&self, predicate: Box<dyn Fn(&M) -> bool + Send>) -> Result<Vec<(String, M)>>;
209
210 /// Count typed documents in the collection
211 fn count(&self) -> Result<usize>;
212}
213
214/// CRDT capability trait - Backend supports field-level conflict resolution
215///
216/// Backends that implement this trait can store structured data and provide
217/// CRDT-based merging at the field level, enabling:
218/// - Delta sync (only changed fields transmitted)
219/// - Automatic conflict resolution
220/// - Optimistic replication
221///
222/// # Implementations
223///
224/// - ✅ `AutomergeIrohBackend` - Native Automerge documents with RocksDB persistence
225/// - ❌ `SimpleBackend` - Blob storage, no CRDT support
226pub trait CrdtCapable: Send + Sync {
227 /// Create a typed collection for CRDT-optimized storage
228 ///
229 /// # Type Parameters
230 ///
231 /// * `M` - Protobuf message type with serde support
232 ///
233 /// # Returns
234 ///
235 /// Thread-safe typed collection handle with CRDT semantics
236 fn typed_collection<M>(&self, name: &str) -> Arc<dyn TypedCollection<M>>
237 where
238 M: Message + Serialize + DeserializeOwned + Default + Clone + 'static;
239}
240
241/// Sync capability trait - Backend has built-in replication
242///
243/// Complete backends that provide integrated P2P synchronization implement this trait.
244///
245/// # Implementations
246///
247/// - ✅ `AutomergeIrohBackend` - Integrated Iroh QUIC transport with custom mesh (ADR-017)
248/// - ❌ `SimpleBackend` - Local storage only, no synchronization
249pub trait SyncCapable: Send + Sync {
250 /// Start background synchronization
251 fn start_sync(&self) -> Result<()>;
252
253 /// Stop background synchronization
254 fn stop_sync(&self) -> Result<()>;
255
256 /// Get current sync statistics
257 ///
258 /// Returns metrics like peer count, bytes sent/received, etc.
259 fn sync_stats(&self) -> Result<SyncStats>;
260}
261
262/// Synchronization statistics
263#[derive(Debug, Clone)]
264pub struct SyncStats {
265 /// Number of connected peers
266 pub peer_count: usize,
267 /// Total bytes sent
268 pub bytes_sent: u64,
269 /// Total bytes received
270 pub bytes_received: u64,
271 /// Last sync timestamp (if applicable)
272 pub last_sync: Option<std::time::SystemTime>,
273}
274
275/// Hierarchical storage capability trait - Backend provides summary and command storage
276///
277/// Backends that implement this trait can provide SummaryStorage and CommandStorage
278/// implementations for hierarchical aggregation and command dissemination.
279///
280/// # Implementations
281///
282/// - ✅ `AutomergeBackend` - Returns AutomergeSummaryStorage and AutomergeCommandStorage
283/// - ❌ `SimpleBackend` - Not supported (no CRDT, no hierarchy)
284///
285/// # Example
286///
287/// ```ignore
288/// use peat_protocol::storage::{HierarchicalStorageCapable, StorageBackend};
289///
290/// fn setup_hierarchical_mode(backend: &dyn HierarchicalStorageCapable) {
291/// let summary_storage = backend.summary_storage();
292/// let command_storage = backend.command_storage();
293///
294/// let aggregator = HierarchicalAggregator::new(summary_storage);
295/// let cmd_coordinator = CommandCoordinator::new(..., command_storage);
296/// }
297/// ```
298pub trait HierarchicalStorageCapable: Send + Sync {
299 /// Create a SummaryStorage implementation for hierarchical aggregation
300 ///
301 /// Returns a thread-safe handle to the summary storage.
302 fn summary_storage(&self) -> Arc<dyn SummaryStorage>;
303
304 /// Create a CommandStorage implementation for command dissemination
305 ///
306 /// Returns a thread-safe handle to the command storage.
307 fn command_storage(&self) -> Arc<dyn CommandStorage>;
308}
309
310#[cfg(test)]
311mod tests {
312 use super::*;
313
314 // Verify TypedCollection is object-safe (can be used as trait object)
315 #[test]
316 fn test_typed_collection_is_object_safe() {
317 use peat_schema::hierarchy::v1::SquadSummary;
318 fn _assert_object_safe(_: &dyn TypedCollection<SquadSummary>) {}
319 }
320
321 // Note: CrdtCapable is intentionally NOT object-safe due to generic method.
322 // This is correct - use concrete backend types:
323 // let backend = AutomergeIrohBackend::new(config);
324 // let collection = backend.typed_collection::<SquadSummary>("squads");
325}