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