//! Replication and sync for StemeDB two-node clusters.
//!
//! This crate implements the sync layer for StemeDB replication:
//!
//! - **Gossip**: Push new assertions to peers immediately after ingestion
//! - **Anti-Entropy**: Periodic Merkle root exchange and diff-based sync
//!
//! # Architecture
//!
//! ```text
//! [IngestWorker]
//!      |
//!      v
//! [GossipBroadcaster] ---> [Peer Nodes]
//!      |
//!      v
//! [MerkleTreeManager] <--> [AntiEntropyWorker]
//! ```
//!
//! # Usage
//!
//! ```ignore
//! use stemedb_sync::{SyncConfig, GossipBroadcaster, AntiEntropyWorker};
//!
//! // Configure sync
//! let config = SyncConfig::new()
//!     .with_peer("http://peer1:18182")
//!     .with_peer("http://peer2:18182");
//!
//! // Create gossip broadcaster
//! let broadcaster = GossipBroadcaster::new(config.peers.clone()).await?;
//!
//! // Start anti-entropy worker (with shared HLC for causal ordering)
//! let local_hlc = Arc::new(uhlc::HLCBuilder::new().build());
//! let worker = AntiEntropyWorker::new(merkle_manager, crdt_store, client, local_hlc, config);
//! tokio::spawn(worker.run());
//! ```

#![forbid(unsafe_code)]
#![warn(missing_docs)]

pub mod anti_entropy;
pub mod config;
pub mod error;
pub mod gossip;
pub mod merkle_manager;

pub use anti_entropy::{AntiEntropyWorker, SyncResult};
pub use config::SyncConfig;
pub use error::{Result, SyncError};
pub use gossip::{GossipBroadcast, GossipBroadcaster};
pub use merkle_manager::MerkleTreeManager;
