dig-rpc-protocol 0.11.0

Canonical DIG-node JSON-RPC protocol: request/response types, the method enum + tier classification, the error-code taxonomy, and an OpenRPC 1.2.6 document generator. The single source of truth both DIG node implementations depend on. Pure types — no I/O, no async, no server logic. (Formerly dig-rpc-types.)
Documentation
//! # dig-rpc-protocol
//!
//! The **canonical DIG-node JSON-RPC protocol** (formerly `dig-rpc-types`). This
//! crate is the single
//! source of truth both DIG node implementations (the digstore `dig-node` crate
//! and the standalone `dig-node` binary) depend on instead of hand-rolling
//! `json!({…})` shapes and ad-hoc error codes:
//!
//! - the JSON-RPC 2.0 [`envelope`] — [`JsonRpcRequest`],
//!   [`JsonRpcResponse`], [`RequestId`], [`Version`];
//! - the canonical [error taxonomy](error) — [`ErrorCode`], the
//!   [`RpcError`] envelope (`{code, message, data:{code, origin}}`), and the one
//!   constructor helper both nodes call;
//! - the [method catalogue](method) — [`Method`] with stable wire names, the
//!   per-method [`Tier`], and the mTLS peer allowlist;
//! - the [wire types](types) for every method's params + results, field-for-field
//!   with the canonical node (network-profile-only fields `Option` + doc-flagged);
//! - the shape-dispatched [peer frame families](frames) — the DHT and PEX wires;
//! - the [OpenRPC 1.2.6 generator](openrpc) — the single discovery document,
//!   generated from the tables above so discovery can never drift.
//!
//! ## What does NOT live here
//!
//! - **No I/O, no async, no server logic.** No axum, no tokio, no transport. The
//!   [`dig-rpc`](https://crates.io/crates/dig-rpc) server crate and the node
//!   implementations build on these types. This crate MUST NOT depend on any
//!   server or service crate.
//! - **No crypto.** Hex identifiers are `String` on the wire; length/charset
//!   validation is the consumer's boundary responsibility.
//!
//! ## Stability
//!
//! 1. [`ErrorCode`] and [`Method`] are `#[non_exhaustive]`; adding a code /
//!    method is additive (match with `_ => …`).
//! 2. [`ErrorCode`] numeric values and machine codes never change once assigned.
//! 3. Method wire names are stable.
//! 4. The tier map and the peer allowlist mirror the canonical node exactly.
//!
//! ## Example — build and inspect an error envelope
//!
//! ```
//! use dig_rpc_protocol::{RpcError, ErrorCode, ErrorOrigin};
//!
//! let e = RpcError::of(ErrorCode::ResourceUnavailable, "not at this root");
//! assert_eq!(e.code, ErrorCode::ResourceUnavailable);
//! assert_eq!(e.data.code, "RESOURCE_UNAVAILABLE");
//! assert_eq!(e.data.origin, ErrorOrigin::Node);
//! ```

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

pub mod envelope;
pub mod error;
pub mod frames;
pub mod method;
pub mod openrpc;
pub mod tier;
pub mod types;

// Re-export the most-used items at the crate root.
pub use envelope::{JsonRpcRequest, JsonRpcResponse, JsonRpcResponseBody, RequestId, Version};
pub use error::{ErrorCode, ErrorData, ErrorOrigin, RpcError};
pub use method::Method;
pub use openrpc::{openrpc_document, OPENRPC_VERSION};
pub use tier::Tier;

/// The interface (wire-schema) version this crate defines. Bumped only on a
/// wire-breaking change; additive changes leave it untouched.
pub const INTERFACE_VERSION: &str = "1";

/// The entry-set staleness bound: a reward distributor whose entry set has not changed in this
/// long **while its reserve is non-zero** MUST be reported stale
/// (`dig-rewards-coin/SPEC.md` v0.1.1 §12.4). Exported because the threshold is part of the wire
/// contract's meaning: a consumer that hardcodes `172_800` from prose drifts the moment the SPEC
/// moves, and every consumer must apply the same bound to the same field
/// ([`GetRewardDistributorResult::last_entry_write_at`](crate::types::GetRewardDistributorResult)).
pub const STALE_ENTRY_SET_SECONDS: u64 = 172_800;

// `CONTENT_MISS_INCONCLUSIVE` is `-32017` as of 0.10.0. It was published as
// `-32015` in 0.9.0, which is dig-node's released `METADATA_TOO_LARGE`; 0.10.0
// declares the consumer-held codes so the next assignment can see them.
// See dig_ecosystem#3128 and `error`'s module docs.

#[cfg(test)]
mod lib_tests {
    use super::STALE_ENTRY_SET_SECONDS;

    /// **Proves:** `STALE_ENTRY_SET_SECONDS` stays pinned to the SPEC §12.4
    /// value (172_800 = 48h) against a careless edit.
    #[test]
    fn stale_entry_set_seconds_is_48_hours() {
        assert_eq!(STALE_ENTRY_SET_SECONDS, 172_800);
    }
}