Skip to main content

rmux_proto/request/
web.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{PaneTargetRef, SessionName};
6
7/// Request payload for the `web-share` command family.
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub enum WebShareRequest {
10    /// Create a new browser-visible share.
11    Create(CreateWebShareRequest),
12    /// List active web shares.
13    List(ListWebSharesRequest),
14    /// Stop one active web share.
15    Stop(StopWebShareRequest),
16    /// Stop every active web share.
17    StopAll(StopAllWebSharesRequest),
18    /// Lookup one active web share without exposing access keys.
19    Lookup(LookupWebShareRequest),
20    /// Return the daemon web-share listener configuration.
21    Config(WebShareConfigRequest),
22}
23
24/// Request payload for `web-share`.
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub struct CreateWebShareRequest {
27    /// Browser-visible scope exposed by this share.
28    pub scope: WebShareScope,
29    /// Optional public WS origin forwarded to the daemon.
30    #[serde(default)]
31    pub public_base_url: Option<String>,
32    /// Optional named tunnel preset spawned by the daemon.
33    #[serde(default)]
34    pub tunnel_provider: Option<String>,
35    /// Optional browser frontend URL used for this share.
36    #[serde(default)]
37    pub frontend_url: Option<String>,
38    /// Optional maximum share lifetime in seconds.
39    #[serde(default)]
40    pub ttl_seconds: Option<u64>,
41    /// Optional absolute expiration timestamp as UNIX seconds.
42    #[serde(default)]
43    pub expires_at_unix: Option<u64>,
44    /// Optional cap for concurrent spectator clients.
45    #[serde(default)]
46    pub max_spectators: Option<u16>,
47    /// Optional cap for concurrent operator clients.
48    #[serde(default)]
49    pub max_operators: Option<u16>,
50    /// Presentation options encoded into generated spectator URLs.
51    #[serde(default)]
52    pub url_options: WebShareUrlOptions,
53    /// Whether clients must provide the out-of-band pairing code during auth.
54    #[serde(default = "default_true")]
55    pub require_pin: bool,
56    /// Optional operator pairing code supplied by the caller.
57    #[serde(default)]
58    pub operator_pin: Option<String>,
59    /// Optional spectator pairing code supplied by the caller.
60    #[serde(default)]
61    pub spectator_pin: Option<String>,
62    /// Terminal palette captured by the CLI for browser-side "User" theme.
63    #[serde(default)]
64    pub terminal_palette: Option<Box<WebTerminalPalette>>,
65    /// Whether an operator URL should be minted.
66    #[serde(default = "default_true")]
67    pub operator: bool,
68    /// Whether a spectator URL should be minted.
69    #[serde(default = "default_true")]
70    pub spectator: bool,
71    /// Internal capability bit; the daemon derives it for operator session shares.
72    #[serde(default)]
73    pub controls: bool,
74    /// Whether the target session should be killed when this share expires.
75    #[serde(default)]
76    pub kill_session_on_expire: bool,
77}
78
79/// Browser-visible scope exposed by a web share.
80#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
81#[serde(rename_all = "snake_case")]
82pub enum WebShareScope {
83    /// Expose exactly one pane.
84    Pane(PaneTargetRef),
85    /// Expose an attached-client view of one session.
86    Session(SessionName),
87}
88
89impl WebShareScope {
90    /// Returns true when this share exposes one pane.
91    #[must_use]
92    pub const fn is_pane(&self) -> bool {
93        matches!(self, Self::Pane(_))
94    }
95
96    /// Returns true when this share exposes one session.
97    #[must_use]
98    pub const fn is_session(&self) -> bool {
99        matches!(self, Self::Session(_))
100    }
101}
102
103impl fmt::Display for WebShareScope {
104    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
105        match self {
106            Self::Pane(target) => target.fmt(formatter),
107            Self::Session(session_name) => session_name.fmt(formatter),
108        }
109    }
110}
111
112/// Browser presentation options for generated web-share URLs.
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
114pub struct WebShareUrlOptions {
115    /// Hide the share navigation bar for this generated URL.
116    #[serde(default)]
117    pub no_navbar: bool,
118    /// Suppress the client-side privacy/disclaimer toast.
119    #[serde(default)]
120    pub no_disclaimer: bool,
121    /// Show the live connected browser count in generated URLs.
122    #[serde(default = "default_show_viewers")]
123    pub show_viewers: bool,
124    /// Optional initial terminal theme for generated spectator URLs.
125    #[serde(default)]
126    pub terminal_theme: Option<WebTerminalTheme>,
127}
128
129impl Default for WebShareUrlOptions {
130    fn default() -> Self {
131        Self {
132            no_navbar: false,
133            no_disclaimer: false,
134            show_viewers: true,
135            terminal_theme: None,
136        }
137    }
138}
139
140const fn default_show_viewers() -> bool {
141    true
142}
143
144const fn default_true() -> bool {
145    true
146}
147
148/// Initial terminal theme selected by the share URL.
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
150#[serde(rename_all = "kebab-case")]
151pub enum WebTerminalTheme {
152    /// Use the owner's captured terminal palette when available.
153    User,
154    /// Use the bundled light browser terminal palette.
155    Light,
156    /// Use the bundled dark browser terminal palette.
157    Dark,
158}
159
160impl WebTerminalTheme {
161    /// Returns the URL fragment value for this terminal theme.
162    #[must_use]
163    pub const fn as_url_value(self) -> &'static str {
164        match self {
165            Self::User => "user",
166            Self::Light => "light",
167            Self::Dark => "dark",
168        }
169    }
170}
171
172/// Browser terminal palette captured from the local terminal.
173#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
174pub struct WebTerminalPalette {
175    /// Default foreground color as `#rrggbb`.
176    pub foreground: String,
177    /// Default background color as `#rrggbb`.
178    pub background: String,
179    /// Cursor color as `#rrggbb`.
180    pub cursor: String,
181    /// ANSI 0-15 palette colors as `#rrggbb`.
182    pub ansi: [String; 16],
183}
184
185/// Request payload for `web-share -l`.
186#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
187pub struct ListWebSharesRequest;
188
189/// Request payload for `web-share -K <id>`.
190#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
191pub struct StopWebShareRequest {
192    /// Share identifier returned by creation.
193    pub share_id: String,
194}
195
196/// Request payload for `web-share -X`.
197#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
198pub struct StopAllWebSharesRequest;
199
200/// Request payload for SDK/browser lookup of share metadata.
201#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
202pub struct LookupWebShareRequest {
203    /// Share identifier to inspect.
204    pub share_id: String,
205}
206
207/// Request payload for daemon web-share listener configuration.
208#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
209pub struct WebShareConfigRequest;