//! gRPC layer for StemeDB node-to-node replication.
//!
//! This crate provides the transport layer for two-node replication:
//!
//! - **Gossip**: Push new assertions to peers immediately after ingestion
//! - **Anti-Entropy**: Periodic Merkle root exchange and diff-based sync
//!
//! # Architecture
//!
//! ```text
//! [Node A]                    [Node B]
//!    |                           |
//!    |--- GossipRequest -------->|   (Push new assertion)
//!    |<-- GossipResponse --------|
//!    |                           |
//!    |--- ExchangeRoots -------->|   (Compare Merkle roots)
//!    |<-- RootsResponse ---------|
//!    |                           |
//!    |--- FetchAssertions ------>|   (Pull missing data)
//!    |<-- AssertionData ---------|
//! ```
//!
//! # Usage
//!
//! ## Client
//!
//! ```ignore
//! use stemedb_rpc::client::SyncClient;
//! use stemedb_rpc::proto::GossipRequest;
//!
//! let client = SyncClient::connect("http://peer:18182").await?;
//! let resp = client.gossip(GossipRequest {
//!     assertion_hash: hash.to_vec(),
//!     assertion_data: data,
//!     hlc_time: ts.time_ntp64,
//!     hlc_counter: 0,
//!     hlc_node_id: node_id.to_vec(),
//! }).await?;
//! ```
//!
//! ## Server
//!
//! ```ignore
//! use stemedb_rpc::server::{SyncServiceHandler, SyncStorage};
//! use stemedb_rpc::proto::sync_service_server::SyncServiceServer;
//! use tonic::transport::Server;
//!
//! let handler = SyncServiceHandler::new(my_storage);
//! Server::builder()
//!     .add_service(SyncServiceServer::new(handler))
//!     .serve("[::1]:18182".parse()?)
//!     .await?;
//! ```

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

pub mod client;
pub mod error;
pub mod server;

/// Generated protobuf types and service definitions.
#[allow(missing_docs)]
pub mod proto {
    tonic::include_proto!("stemedb.sync.v1");
}

pub use client::{RetryConfig, SyncClient};
pub use error::{Result, RpcError};
pub use server::{SyncServiceHandler, SyncStorage};
