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