1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//! NetworkManager secret agent for credential prompting over D-Bus.
//!
//! When NetworkManager needs credentials it does not already have — a Wi-Fi
//! password was forgotten, a VPN token expired, an 802.1X password is required
//! — it calls every registered **secret agent** via D-Bus. This module lets
//! `nmrs` consumers register such an agent and respond to those requests
//! without touching raw D-Bus.
//!
//! # Three-stream model
//!
//! [`SecretAgentBuilder::register()`](crate::agent::SecretAgentBuilder::register)
//! returns a handle and three logical streams:
//!
//! 1. **Request stream** — the primary
//! [`mpsc::Receiver<SecretRequest>`](futures::channel::mpsc::Receiver)
//! returned alongside the handle. Each item is a credential prompt from
//! NetworkManager. Respond through the attached
//! [`SecretResponder`](crate::agent::SecretResponder).
//!
//! 2. **Cancellation stream** — accessed via
//! [`SecretAgentHandle::cancellations()`](crate::agent::SecretAgentHandle::cancellations). Yields
//! [`CancelReason`](crate::agent::CancelReason) items when
//! NetworkManager aborts a pending request. The agent replies to
//! NetworkManager automatically; this stream exists so the consumer can
//! tear down any UI it may have shown.
//!
//! 3. **Store event stream** — accessed via
//! [`SecretAgentHandle::store_events()`](crate::agent::SecretAgentHandle::store_events). Yields
//! [`SecretStoreEvent`](crate::agent::SecretStoreEvent) items when
//! NetworkManager asks the agent to save or delete persisted secrets.
//! Since `nmrs` delegates persistence to the consumer, these events are
//! optional and the agent always acknowledges them.
//!
//! # Lifecycle
//!
//! ```text
//! SecretAgent::builder()
//! .with_identifier("com.example.MyApp")
//! .register().await?
//! │
//! ├── (SecretAgentHandle, request stream)
//! │
//! │ ┌──────── consumer loop ────────┐
//! │ │ while let Some(req) = rx … { │
//! │ │ req.responder.wifi_psk(…) │
//! │ │ } │
//! │ └───────────────────────────────┘
//! │
//! └── handle.unregister().await?
//! ```
//!
//! If NetworkManager restarts while the agent is running, call
//! [`SecretAgentHandle::reregister()`](crate::agent::SecretAgentHandle::reregister)
//! to re-register.
//!
//! # Example
//!
//! ```no_run
//! use futures::StreamExt;
//! use nmrs::agent::{SecretAgent, SecretAgentFlags, SecretSetting};
//!
//! # async fn run() -> nmrs::Result<()> {
//! let (handle, mut requests) = SecretAgent::builder()
//! .with_identifier("com.example.demo")
//! .register()
//! .await?;
//!
//! while let Some(req) = requests.next().await {
//! if !req.flags.contains(SecretAgentFlags::ALLOW_INTERACTION) {
//! req.responder.no_secrets().await?;
//! continue;
//! }
//! match req.setting {
//! SecretSetting::WifiPsk { ref ssid } => {
//! println!("Password needed for {ssid}");
//! req.responder.wifi_psk("secret").await?;
//! }
//! _ => req.responder.cancel().await?,
//! }
//! }
//!
//! handle.unregister().await?;
//! # Ok(())
//! # }
//! ```
pub
pub use ;
pub use ;
/// Type alias so agent consumers only need one error type.
pub type AgentError = crateConnectionError;