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 sync_token: String,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct CloudEnterpriseLicenseInfo {
166    pub id: String,
167    pub name: String,
168    pub domain: String,
169    #[serde(default)]
170    pub plan: Option<CloudPlanInfo>,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct UserMeResponse {
175    pub user: CloudUserInfo,
176    #[serde(default)]
177    pub customer: Option<CloudCustomerInfo>,
178    #[serde(default)]
179    pub tenants: Vec<CloudTenantInfo>,
180    #[serde(default)]
181    pub enterprise: Option<CloudEnterpriseLicenseInfo>,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct CloudListResponse<T> {
186    pub data: Vec<T>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct RegistryToken {
191    pub registry: String,
192    pub username: String,
193    pub token: String,
194    pub repository: String,
195    pub tag: String,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct DeployResponse {
200    pub status: String,
201    pub app_url: Option<String>,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
205pub struct CloudStatusResponse {
206    pub status: String,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct SetSecretsRequest {
211    pub secrets: HashMap<String, String>,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct CheckoutRequest {
216    pub price_id: String,
217    pub region: String,
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub redirect_uri: Option<String>,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct CheckoutResponse {
224    pub checkout_url: String,
225    pub transaction_id: String,
226    pub checkout_session_id: String,
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
230#[serde(rename_all = "snake_case")]
231pub enum ProvisioningEventType {
232    SubscriptionCreated,
233    TenantCreated,
234    DatabaseCreated,
235    SecretsStored,
236    VmProvisioningStarted,
237    VmProvisioningProgress,
238    VmProvisioned,
239    SecretsConfigured,
240    InfrastructureReady,
241    TenantReady,
242    ProvisioningFailed,
243}
244
245#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct ProvisioningEvent {
247    pub tenant_id: String,
248    pub event_type: ProvisioningEventType,
249    pub status: String,
250    #[serde(default)]
251    pub message: Option<String>,
252    #[serde(default)]
253    pub app_url: Option<String>,
254    #[serde(default)]
255    pub fly_app_name: Option<String>,
256}
257
258#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct CheckoutEvent {
260    pub checkout_session_id: String,
261    pub tenant_id: String,
262    pub tenant_name: String,
263    pub event_type: ProvisioningEventType,
264    pub status: String,
265    #[serde(default)]
266    pub message: Option<String>,
267    #[serde(default)]
268    pub app_url: Option<String>,
269    #[serde(default)]
270    pub fly_app_name: Option<String>,
271}
272
273#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
274pub struct CloudLogEntry {
275    pub timestamp: String,
276    pub message: String,
277    #[serde(default)]
278    pub level: Option<String>,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct CloudLogsResponse {
283    pub logs: Vec<CloudLogEntry>,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
287pub struct ListSecretsResponse {
288    pub keys: Vec<String>,
289}
290
291#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
292pub struct SetCustomDomainRequest {
293    pub domain: String,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
297pub struct DnsInstructions {
298    pub record_type: String,
299    pub host: String,
300    pub value: String,
301    pub ttl: u32,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
305pub struct CustomDomainResponse {
306    pub domain: String,
307    pub status: String,
308    pub verified: bool,
309    pub dns_target: String,
310    pub dns_instructions: DnsInstructions,
311    #[serde(default, skip_serializing_if = "Option::is_none")]
312    pub created_at: Option<String>,
313    #[serde(default, skip_serializing_if = "Option::is_none")]
314    pub verified_at: Option<String>,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct ActivityRequest {
319    pub event: String,
320    pub timestamp: String,
321    pub data: ActivityData,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
325pub struct ActivityData {
326    pub user_id: String,
327}
328
329pub type ApiResponse<T> = CloudApiResponse<T>;
330pub type ApiError = CloudApiError;
331pub type ApiErrorDetail = CloudApiErrorDetail;
332pub type UserInfo = CloudUserInfo;
333pub type CustomerInfo = CloudCustomerInfo;
334pub type PlanInfo = CloudPlanInfo;
335pub type Plan = CloudPlan;
336pub type TenantInfo = CloudTenantInfo;
337pub type Tenant = CloudTenant;
338pub type TenantStatus = CloudTenantStatusResponse;
339pub type TenantSecrets = CloudTenantSecrets;
340pub type ListResponse<T> = CloudListResponse<T>;
341pub type StatusResponse = CloudStatusResponse;
342pub type LogEntry = CloudLogEntry;
343pub type LogsResponse = CloudLogsResponse;
344pub type EnterpriseLicenseInfo = CloudEnterpriseLicenseInfo;