dig_node_control_interface/lib.rs
1//! # dig-node-control-interface — the canonical client ⇄ dig-node CONTROL interface contract
2//!
3//! This crate is the single source of truth for the management/query surface a client — the CLI
4//! `dign`, the browser extension, dig-app, or hub — uses to **control and query a running
5//! dig-node**: node configuration, cache configuration, hosted/pinned stores, §21 whole-store sync,
6//! the peer network, subscription lifecycle, the auto-update beacon, live log level, and the
7//! control-token pairing handshake. Both the node (the server side, dispatching these calls) and
8//! every client (the callers) depend on THIS crate rather than each maintaining a byte-identical
9//! copy of the method catalog, so the two can never silently drift.
10//!
11//! ## The catalog
12//!
13//! - [`ControlMethod`] — every control method's stable wire name, auth requirement, routing, and
14//! category; the enumeration a machine reads to discover the whole surface.
15//! - [`params`] — a typed request-params struct per method, each bound (via [`ControlCall`]) to its
16//! method and its typed result.
17//! - [`results`] — the typed result payloads, field-for-field with what dig-node emits.
18//! - [`error`] — the stable control-error taxonomy ([`ControlErrorCode`]) + the [`ControlError`]
19//! envelope a client branches its UX off.
20//! - [`envelope`] — the minimal JSON-RPC 2.0 request/response the catalog rides in.
21//! - [`traits`] — the two contract traits: [`ControlClient`] (client-facing: build request / parse
22//! response) and [`ControlHandler`] (node-facing: implement to serve, with a routing dispatcher).
23//!
24//! ## Boundary (the 6th directed-boundary contract crate)
25//!
26//! - **dig-rpc-protocol** — node ⇄ node peer wire (PublicRead + Peer tiers).
27//! - **dig-ipc-protocol** — app ⇄ node local session/signing envelope (the transport a client
28//! authenticates over).
29//! - **dig-node-control-interface (this crate)** — the CONTROL METHOD CATALOG a client sends
30//! *inside* that authenticated channel (or over loopback-mTLS + a signed control token, per
31//! CLAUDE.md §5.3): the method names, parameter/result types, and error taxonomy.
32//!
33//! This crate is deliberately **transport-agnostic** — it describes WHAT a client can ask a node to
34//! do and what the node replies, not HOW the bytes travel. Consumers pick the transport and carry
35//! these types over it.
36//!
37//! ## Example — build a typed request and parse the response
38//!
39//! ```
40//! use dig_node_control_interface::{
41//! params::SetCapParams,
42//! traits::{build_request, parse_response},
43//! envelope::JsonRpcResponse,
44//! };
45//! use serde_json::json;
46//!
47//! let call = SetCapParams { cap_bytes: 128 * 1024 * 1024 };
48//! let req = build_request(1.into(), &call);
49//! assert_eq!(req.method, "control.cache.setCap");
50//!
51//! // The node replies with the applied cap; parse it back into the typed result.
52//! let resp = JsonRpcResponse::success(1.into(), json!({ "cap_bytes": 128 * 1024 * 1024 }));
53//! let out = parse_response::<SetCapParams>(resp).unwrap();
54//! assert_eq!(out.cap_bytes, 128 * 1024 * 1024);
55//! ```
56
57#![forbid(unsafe_code)]
58#![warn(missing_docs)]
59
60pub mod envelope;
61pub mod error;
62pub mod method;
63pub mod params;
64pub mod results;
65pub mod traits;
66
67#[cfg(test)]
68mod kats;
69
70pub use error::{ControlError, ControlErrorCode, ControlErrorData};
71pub use method::{Category, ControlMethod, Routing};
72pub use traits::{ControlCall, ControlClient, ControlHandler, DefaultControlClient};
73
74/// The crate's semantic version, exposed so consumers can assert compatibility at runtime without
75/// re-parsing `Cargo.toml`.
76pub const CRATE_VERSION: &str = env!("CARGO_PKG_VERSION");