runbeam_sdk/runbeam_api/
types.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4/// Runbeam API error type
5///
6/// Represents all possible errors that can occur when interacting with
7/// the Runbeam Cloud API or performing related operations.
8#[derive(Debug)]
9pub enum RunbeamError {
10    /// JWT validation failed
11    JwtValidation(String),
12    /// API request failed (network, HTTP, or response parsing error)
13    Api(ApiError),
14    /// Token storage operation failed
15    Storage(crate::storage::StorageError),
16    /// Configuration error
17    Config(String),
18}
19
20impl fmt::Display for RunbeamError {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        match self {
23            RunbeamError::JwtValidation(msg) => write!(f, "JWT validation failed: {}", msg),
24            RunbeamError::Api(err) => write!(f, "API error: {}", err),
25            RunbeamError::Storage(err) => write!(f, "Storage error: {}", err),
26            RunbeamError::Config(msg) => write!(f, "Configuration error: {}", msg),
27        }
28    }
29}
30
31impl std::error::Error for RunbeamError {}
32
33impl From<ApiError> for RunbeamError {
34    fn from(err: ApiError) -> Self {
35        RunbeamError::Api(err)
36    }
37}
38
39impl From<crate::storage::StorageError> for RunbeamError {
40    fn from(err: crate::storage::StorageError) -> Self {
41        RunbeamError::Storage(err)
42    }
43}
44
45impl From<jsonwebtoken::errors::Error> for RunbeamError {
46    fn from(err: jsonwebtoken::errors::Error) -> Self {
47        RunbeamError::JwtValidation(err.to_string())
48    }
49}
50
51/// API-specific errors
52#[derive(Debug)]
53pub enum ApiError {
54    /// Network error (connection, timeout, etc.)
55    Network(String),
56    /// HTTP error with status code
57    Http { status: u16, message: String },
58    /// Failed to parse response
59    Parse(String),
60    /// Request building failed
61    Request(String),
62}
63
64impl fmt::Display for ApiError {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match self {
67            ApiError::Network(msg) => write!(f, "Network error: {}", msg),
68            ApiError::Http { status, message } => {
69                write!(f, "HTTP {} error: {}", status, message)
70            }
71            ApiError::Parse(msg) => write!(f, "Parse error: {}", msg),
72            ApiError::Request(msg) => write!(f, "Request error: {}", msg),
73        }
74    }
75}
76
77impl std::error::Error for ApiError {}
78
79impl From<reqwest::Error> for ApiError {
80    fn from(err: reqwest::Error) -> Self {
81        if err.is_timeout() {
82            ApiError::Network("Request timeout".to_string())
83        } else if err.is_connect() {
84            ApiError::Network(format!("Connection failed: {}", err))
85        } else if let Some(status) = err.status() {
86            ApiError::Http {
87                status: status.as_u16(),
88                message: err.to_string(),
89            }
90        } else {
91            ApiError::Network(err.to_string())
92        }
93    }
94}
95
96/// User information from JWT claims
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct UserInfo {
99    pub id: String,
100    pub email: String,
101    pub name: String,
102}
103
104/// User authentication token (JWT)
105///
106/// This token is used for authenticating user actions with the Runbeam Cloud API.
107/// It has a shorter lifespan than machine tokens and is typically issued after
108/// a user successfully logs in via the browser-based OAuth flow.
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct UserToken {
111    /// JWT token for API authentication
112    pub token: String,
113    /// Token expiration timestamp (seconds since Unix epoch)
114    #[serde(default)]
115    pub expires_at: Option<i64>,
116    /// User information from JWT claims
117    #[serde(default)]
118    pub user: Option<UserInfo>,
119}
120
121impl UserToken {
122    /// Create a new user token
123    pub fn new(token: String, expires_at: Option<i64>, user: Option<UserInfo>) -> Self {
124        Self {
125            token,
126            expires_at,
127            user,
128        }
129    }
130}
131
132/// Team information from JWT claims
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct TeamInfo {
135    pub id: String,
136    pub name: String,
137}
138
139/// Gateway information returned from authorize endpoint
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct GatewayInfo {
142    pub id: String,
143    pub code: String,
144    pub name: String,
145    #[serde(default)]
146    pub authorized_by: Option<AuthorizedBy>,
147}
148
149/// User who authorized the gateway
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct AuthorizedBy {
152    pub id: String,
153    pub name: String,
154    pub email: String,
155}
156
157/// Response from Runbeam Cloud authorize endpoint
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct AuthorizeResponse {
160    pub machine_token: String,
161    pub expires_in: f64,
162    pub expires_at: String,
163    pub gateway: GatewayInfo,
164    #[serde(default)]
165    pub abilities: Vec<String>,
166}
167
168/// Config change summary from list endpoint
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct ConfigChange {
171    pub id: String,
172    pub timestamp: String,
173    pub summary: String,
174}
175
176/// Detailed config change with full content
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct ConfigChangeDetail {
179    pub id: String,
180    pub content: String,
181    #[serde(default)]
182    pub metadata: Option<serde_json::Value>,
183}
184
185/// Response after acknowledging/reporting config change
186#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct ConfigChangeAck {
188    pub success: bool,
189    #[serde(default)]
190    pub message: Option<String>,
191}