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)]
28    pub name: Option<String>,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct CloudCustomerInfo {
33    pub id: String,
34    #[serde(default)]
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)]
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)]
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)]
84    pub subscription_id: Option<String>,
85    #[serde(default)]
86    pub subscription_status: Option<SubscriptionStatus>,
87    #[serde(default)]
88    pub app_id: Option<String>,
89    #[serde(default)]
90    pub hostname: Option<String>,
91    #[serde(default)]
92    pub region: Option<String>,
93    #[serde(default)]
94    pub status: Option<CloudTenantStatus>,
95    #[serde(default)]
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    pub fly_app_name: Option<String>,
107    pub fly_hostname: Option<String>,
108    #[serde(default)]
109    pub hostname: Option<String>,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
113pub struct CloudTenantStatusResponse {
114    pub status: String,
115    #[serde(default)]
116    pub message: Option<String>,
117    #[serde(default)]
118    pub app_url: Option<String>,
119    #[serde(default)]
120    pub secrets_url: Option<String>,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct CloudTenantSecrets {
125    pub jwt_secret: String,
126    pub database_url: String,
127    pub internal_database_url: String,
128    pub app_url: String,
129    #[serde(default, skip_serializing_if = "Option::is_none")]
130    pub sync_token: Option<String>,
131    #[serde(default, skip_serializing_if = "Option::is_none")]
132    pub anthropic_api_key: Option<String>,
133    #[serde(default, skip_serializing_if = "Option::is_none")]
134    pub openai_api_key: Option<String>,
135    #[serde(default, skip_serializing_if = "Option::is_none")]
136    pub gemini_api_key: Option<String>,
137}
138
139#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
140pub struct SetExternalDbAccessRequest {
141    pub enabled: bool,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct ExternalDbAccessResponse {
146    pub tenant_id: String,
147    pub external_db_access: bool,
148    pub database_url: String,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct RotateCredentialsResponse {
153    pub status: String,
154    pub message: String,
155    pub internal_database_url: String,
156    pub external_database_url: String,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct RotateSyncTokenResponse {
161    pub status: String,
162    pub sync_token: String,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct UserMeResponse {
167    pub user: CloudUserInfo,
168    #[serde(default)]
169    pub customer: Option<CloudCustomerInfo>,
170    #[serde(default)]
171    pub tenants: Vec<CloudTenantInfo>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct CloudListResponse<T> {
176    pub data: Vec<T>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct RegistryToken {
181    pub registry: String,
182    pub username: String,
183    pub token: String,
184    pub repository: String,
185    pub tag: String,
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct DeployResponse {
190    pub status: String,
191    pub app_url: Option<String>,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
195pub struct CloudStatusResponse {
196    pub status: String,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct SetSecretsRequest {
201    pub secrets: HashMap<String, String>,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct CheckoutRequest {
206    pub price_id: String,
207    pub region: String,
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub redirect_uri: Option<String>,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct CheckoutResponse {
214    pub checkout_url: String,
215    pub transaction_id: String,
216    pub checkout_session_id: String,
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
220#[serde(rename_all = "snake_case")]
221pub enum ProvisioningEventType {
222    SubscriptionCreated,
223    TenantCreated,
224    DatabaseCreated,
225    SecretsStored,
226    VmProvisioningStarted,
227    VmProvisioningProgress,
228    VmProvisioned,
229    SecretsConfigured,
230    InfrastructureReady,
231    TenantReady,
232    ProvisioningFailed,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct ProvisioningEvent {
237    pub tenant_id: String,
238    pub event_type: ProvisioningEventType,
239    pub status: String,
240    #[serde(default)]
241    pub message: Option<String>,
242    #[serde(default)]
243    pub app_url: Option<String>,
244    #[serde(default)]
245    pub fly_app_name: Option<String>,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct CheckoutEvent {
250    pub checkout_session_id: String,
251    pub tenant_id: String,
252    pub tenant_name: String,
253    pub event_type: ProvisioningEventType,
254    pub status: String,
255    #[serde(default)]
256    pub message: Option<String>,
257    #[serde(default)]
258    pub app_url: Option<String>,
259    #[serde(default)]
260    pub fly_app_name: Option<String>,
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
264pub struct CloudLogEntry {
265    pub timestamp: String,
266    pub message: String,
267    #[serde(default)]
268    pub level: Option<String>,
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct CloudLogsResponse {
273    pub logs: Vec<CloudLogEntry>,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
277pub struct ListSecretsResponse {
278    pub keys: Vec<String>,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
282pub struct SetCustomDomainRequest {
283    pub domain: String,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
287pub struct DnsInstructions {
288    pub record_type: String,
289    pub host: String,
290    pub value: String,
291    pub ttl: u32,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
295pub struct CustomDomainResponse {
296    pub domain: String,
297    pub status: String,
298    pub verified: bool,
299    pub dns_target: String,
300    pub dns_instructions: DnsInstructions,
301    #[serde(default, skip_serializing_if = "Option::is_none")]
302    pub created_at: Option<String>,
303    #[serde(default, skip_serializing_if = "Option::is_none")]
304    pub verified_at: Option<String>,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct ActivityRequest {
309    pub event: String,
310    pub timestamp: String,
311    pub data: ActivityData,
312}
313
314#[derive(Debug, Clone, Serialize, Deserialize)]
315pub struct ActivityData {
316    pub user_id: String,
317}
318
319pub type ApiResponse<T> = CloudApiResponse<T>;
320pub type ApiError = CloudApiError;
321pub type ApiErrorDetail = CloudApiErrorDetail;
322pub type UserInfo = CloudUserInfo;
323pub type CustomerInfo = CloudCustomerInfo;
324pub type PlanInfo = CloudPlanInfo;
325pub type Plan = CloudPlan;
326pub type TenantInfo = CloudTenantInfo;
327pub type Tenant = CloudTenant;
328pub type TenantStatus = CloudTenantStatusResponse;
329pub type TenantSecrets = CloudTenantSecrets;
330pub type ListResponse<T> = CloudListResponse<T>;
331pub type StatusResponse = CloudStatusResponse;
332pub type LogEntry = CloudLogEntry;
333pub type LogsResponse = CloudLogsResponse;