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,
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;