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