Skip to main content

systemprompt_models/api/
cloud.rs

1//! Cloud Management API types shared between CLI and API server.
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct CloudApiResponse<T> {
9    pub data: T,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct CloudApiError {
14    pub error: CloudApiErrorDetail,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct CloudApiErrorDetail {
19    pub code: String,
20    pub message: String,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct CloudUserInfo {
25    pub id: String,
26    pub email: String,
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub name: Option<String>,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct CloudCustomerInfo {
33    pub id: String,
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub status: Option<String>,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
39#[serde(rename_all = "snake_case")]
40pub enum SubscriptionStatus {
41    Active,
42    Trialing,
43    PastDue,
44    Paused,
45    Canceled,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct CloudPlanInfo {
50    #[serde(default, skip_serializing_if = "Option::is_none")]
51    pub id: Option<String>,
52    pub name: String,
53    pub memory_mb: i32,
54    pub volume_gb: i32,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
58pub struct CloudPlan {
59    pub id: String,
60    pub name: String,
61    pub paddle_price_id: String,
62    #[serde(default)]
63    pub memory_mb_default: i32,
64    #[serde(default)]
65    pub volume_gb: i32,
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub max_tenants: Option<i32>,
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
71#[serde(rename_all = "snake_case")]
72pub enum CloudTenantStatus {
73    Pending,
74    Active,
75    Suspended,
76    Deleted,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct CloudTenantInfo {
81    pub id: String,
82    pub name: String,
83    #[serde(default, skip_serializing_if = "Option::is_none")]
84    pub subscription_id: Option<String>,
85    #[serde(default, skip_serializing_if = "Option::is_none")]
86    pub subscription_status: Option<SubscriptionStatus>,
87    #[serde(default, skip_serializing_if = "Option::is_none")]
88    pub app_id: Option<String>,
89    #[serde(default, skip_serializing_if = "Option::is_none")]
90    pub hostname: Option<String>,
91    #[serde(default, skip_serializing_if = "Option::is_none")]
92    pub region: Option<String>,
93    #[serde(default, skip_serializing_if = "Option::is_none")]
94    pub status: Option<CloudTenantStatus>,
95    #[serde(default, skip_serializing_if = "Option::is_none")]
96    pub plan: Option<CloudPlanInfo>,
97    #[serde(default)]
98    pub external_db_access: bool,
99    pub database_url: String,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
103pub struct CloudTenant {
104    pub id: String,
105    pub name: String,
106    #[serde(skip_serializing_if = "Option::is_none")]
107    pub fly_app_name: Option<String>,
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub fly_hostname: Option<String>,
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub hostname: Option<String>,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
115pub struct CloudTenantStatusResponse {
116    pub status: String,
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub message: Option<String>,
119    #[serde(default, skip_serializing_if = "Option::is_none")]
120    pub app_url: Option<String>,
121    #[serde(default, skip_serializing_if = "Option::is_none")]
122    pub secrets_url: Option<String>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct CloudTenantSecrets {
127    pub jwt_secret: String,
128    pub database_url: String,
129    pub internal_database_url: String,
130    pub app_url: String,
131    #[serde(default, skip_serializing_if = "Option::is_none")]
132    pub sync_token: Option<String>,
133    #[serde(default, skip_serializing_if = "Option::is_none")]
134    pub anthropic_api_key: Option<String>,
135    #[serde(default, skip_serializing_if = "Option::is_none")]
136    pub openai_api_key: Option<String>,
137    #[serde(default, skip_serializing_if = "Option::is_none")]
138    pub gemini_api_key: Option<String>,
139}
140
141#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
142pub struct SetExternalDbAccessRequest {
143    pub enabled: bool,
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct ExternalDbAccessResponse {
148    pub tenant_id: String,
149    pub external_db_access: bool,
150    pub database_url: String,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct RotateCredentialsResponse {
155    pub status: String,
156    pub message: String,
157    pub internal_database_url: String,
158    pub external_database_url: String,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct RotateSyncTokenResponse {
163    pub sync_token: String,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct CloudEnterpriseLicenseInfo {
168    pub id: String,
169    pub name: String,
170    pub domain: String,
171    #[serde(default, skip_serializing_if = "Option::is_none")]
172    pub plan: Option<CloudPlanInfo>,
173}
174
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct UserMeResponse {
177    pub user: CloudUserInfo,
178    #[serde(default, skip_serializing_if = "Option::is_none")]
179    pub customer: Option<CloudCustomerInfo>,
180    #[serde(default)]
181    pub tenants: Vec<CloudTenantInfo>,
182    #[serde(default, skip_serializing_if = "Option::is_none")]
183    pub enterprise: Option<CloudEnterpriseLicenseInfo>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct CloudListResponse<T> {
188    pub data: Vec<T>,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct RegistryToken {
193    pub registry: String,
194    pub username: String,
195    pub token: String,
196    pub repository: String,
197    pub tag: String,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct DeployResponse {
202    pub status: String,
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub app_url: Option<String>,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
208pub struct CloudStatusResponse {
209    pub status: String,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct SetSecretsRequest {
214    pub secrets: HashMap<String, String>,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct CheckoutRequest {
219    pub price_id: String,
220    pub region: String,
221    #[serde(skip_serializing_if = "Option::is_none")]
222    pub redirect_uri: Option<String>,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct CheckoutResponse {
227    pub checkout_url: String,
228    pub transaction_id: String,
229    pub checkout_session_id: String,
230}
231
232#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
233#[serde(rename_all = "snake_case")]
234pub enum ProvisioningEventType {
235    SubscriptionCreated,
236    TenantCreated,
237    DatabaseCreated,
238    SecretsStored,
239    VmProvisioningStarted,
240    VmProvisioningProgress,
241    VmProvisioned,
242    SecretsConfigured,
243    InfrastructureReady,
244    TenantReady,
245    ProvisioningFailed,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct ProvisioningEvent {
250    pub tenant_id: String,
251    pub event_type: ProvisioningEventType,
252    pub status: String,
253    #[serde(default, skip_serializing_if = "Option::is_none")]
254    pub message: Option<String>,
255    #[serde(default, skip_serializing_if = "Option::is_none")]
256    pub app_url: Option<String>,
257    #[serde(default, skip_serializing_if = "Option::is_none")]
258    pub fly_app_name: Option<String>,
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct CheckoutEvent {
263    pub checkout_session_id: String,
264    pub tenant_id: String,
265    pub tenant_name: String,
266    pub event_type: ProvisioningEventType,
267    pub status: String,
268    #[serde(default, skip_serializing_if = "Option::is_none")]
269    pub message: Option<String>,
270    #[serde(default, skip_serializing_if = "Option::is_none")]
271    pub app_url: Option<String>,
272    #[serde(default, skip_serializing_if = "Option::is_none")]
273    pub fly_app_name: Option<String>,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
277pub struct CloudLogEntry {
278    pub timestamp: String,
279    pub message: String,
280    #[serde(default, skip_serializing_if = "Option::is_none")]
281    pub level: Option<String>,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct CloudLogsResponse {
286    pub logs: Vec<CloudLogEntry>,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
290pub struct ListSecretsResponse {
291    pub keys: Vec<String>,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
295pub struct SetCustomDomainRequest {
296    pub domain: String,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
300pub struct DnsInstructions {
301    pub record_type: String,
302    pub host: String,
303    pub value: String,
304    pub ttl: u32,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
308pub struct CustomDomainResponse {
309    pub domain: String,
310    pub status: String,
311    pub verified: bool,
312    pub dns_target: String,
313    pub dns_instructions: DnsInstructions,
314    #[serde(default, skip_serializing_if = "Option::is_none")]
315    pub created_at: Option<String>,
316    #[serde(default, skip_serializing_if = "Option::is_none")]
317    pub verified_at: Option<String>,
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct ActivityRequest {
322    pub event: String,
323    pub timestamp: String,
324    pub data: ActivityData,
325}
326
327#[derive(Debug, Clone, Serialize, Deserialize)]
328pub struct ActivityData {
329    pub user_id: String,
330}
331
332pub type ApiResponse<T> = CloudApiResponse<T>;
333pub type ApiError = CloudApiError;
334pub type ApiErrorDetail = CloudApiErrorDetail;
335pub type UserInfo = CloudUserInfo;
336pub type CustomerInfo = CloudCustomerInfo;
337pub type PlanInfo = CloudPlanInfo;
338pub type Plan = CloudPlan;
339pub type TenantInfo = CloudTenantInfo;
340pub type Tenant = CloudTenant;
341pub type TenantStatus = CloudTenantStatusResponse;
342pub type TenantSecrets = CloudTenantSecrets;
343pub type ListResponse<T> = CloudListResponse<T>;
344pub type StatusResponse = CloudStatusResponse;
345pub type LogEntry = CloudLogEntry;
346pub type LogsResponse = CloudLogsResponse;
347pub type EnterpriseLicenseInfo = CloudEnterpriseLicenseInfo;