nym_sdk_session/lib.rs
1// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: Apache-2.0
3
4//! # nym-sdk-session
5//!
6//! A provisioning facade over `nym-registration-client`,
7//! `nym-bandwidth-controller`, and the credential store. From a caller-supplied
8//! mnemonic it deposits NYM and issues + persists zk-nym WireGuard ticketbooks,
9//! selects gateways (by identity / two-letter country code / random), and
10//! registers them, returning the per-hop WireGuard configuration the dVPN
11//! datapath needs. Shared by both mixnet and dvpn modes.
12//!
13//! ## Registration reuse
14//!
15//! Registrations are persisted (client WireGuard key + assigned configuration,
16//! in `registrations.json` under `data_path`) and served back on later
17//! `register_*` calls against the same network/gateway/role — no gateway
18//! exchange, **no ticket spent**, resuming the gateway-side peer's remaining
19//! bandwidth allowance. Cached registrations are validated by use: gate tunnel
20//! bring-up with `Tunnel::await_established` (in `smoldvpn`) and, when a
21//! hop fails to establish, call [`Session::invalidate_registration`] for it and
22//! register again (which spends a ticket and persists the fresh peer).
23//! Default-on; opt out via `SessionConfig::reuse_registrations` (see its doc
24//! for the privacy trade-off). The cache file holds WireGuard private keys —
25//! the same secret-sensitivity class as the credential store beside it.
26//!
27//! ## Signer-failure tolerance
28//!
29//! Unresponsive ecash signers are a normal operating condition, not an error to
30//! hang on. The session bounds every read-only global-signing-data fetch with a
31//! per-call timeout ([`TimeoutFetcher`], [`DEFAULT_PUBLIC_DATA_TIMEOUT`]) — the
32//! deposit/issuance call is deliberately exempt — and bounds provisioning
33//! overall, surfacing [`SessionError::ProvisioningTimeout`] instead of blocking.
34//! An issued (paid-for) ticketbook is persisted even when the signing data
35//! needed to *spend* it cannot currently be fetched: retries never re-deposit,
36//! spends during the outage fail fast with a clear error, and everything works
37//! again the moment enough signers return.
38//!
39//! ```no_run
40//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
41//! use nym_sdk_session::{GatewaySpec, Session, SessionConfig};
42//! use tokio_util::sync::CancellationToken;
43//!
44//! // Provisions once and tops up a live tunnel from stored tickets; opt into background
45//! // re-issuance with `.with_automatic_topups(..)`.
46//! let config = SessionConfig::new(
47//! "..".parse()?,
48//! nym_network_defaults::NymNetworkDetails::new_mainnet(),
49//! "/tmp/dvpn".into(),
50//! );
51//! let session = Session::new(config, CancellationToken::new()).await?;
52//!
53//! // Two-hop: entry in Germany, random exit.
54//! let reg = session
55//! .register_two_hop(&GatewaySpec::Country("DE".into()), &GatewaySpec::Random)
56//! .await?;
57//! # let _ = reg; Ok(())
58//! # }
59//! ```
60
61mod config;
62mod dvpn;
63mod error;
64mod fetcher;
65mod gateway;
66mod registration_cache;
67mod session;
68
69pub use config::{RestockPolicy, SessionConfig};
70pub use dvpn::QuicBridge;
71pub use error::SessionError;
72pub use fetcher::{SignerTimeout, TimeoutFetcher, DEFAULT_PUBLIC_DATA_TIMEOUT};
73pub use gateway::{GatewayInfo, GatewaySpec, SelectedGateway, WgRole};
74pub use session::{HopConfig, Registration, Session};