Skip to main content

systemprompt_models/api/cloud/
mod.rs

1//! Cloud Management API types shared between CLI and API server.
2
3mod provisioning;
4
5pub use provisioning::{
6    ActivityData, ActivityRequest, CheckoutEvent, CheckoutRequest, CheckoutResponse,
7    DeployResponse, ProvisioningEvent, ProvisioningEventType,
8};
9
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12use std::collections::HashMap;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct CloudApiResponse<T> {
16    pub data: T,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct CloudApiError {
21    pub error: CloudApiErrorDetail,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct CloudApiErrorDetail {
26    pub code: String,
27    pub message: String,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct CloudUserInfo {
32    pub id: systemprompt_identifiers::UserId,
33    pub email: String,
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub name: Option<String>,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct CloudCustomerInfo {
40    pub id: String,
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    pub status: Option<String>,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46#[serde(rename_all = "snake_case")]
47pub enum SubscriptionStatus {
48    Active,
49    Trialing,
50    PastDue,
51    Paused,
52    Canceled,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct CloudPlanInfo {
57    #[serde(default, skip_serializing_if = "Option::is_none")]
58    pub id: Option<String>,
59    pub name: String,
60    pub memory_mb: i32,
61    pub volume_gb: i32,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
65pub struct CloudPlan {
66    pub id: String,
67    pub name: String,
68    pub paddle_price_id: systemprompt_identifiers::PriceId,
69    #[serde(default)]
70    pub memory_mb_default: i32,
71    #[serde(default)]
72    pub volume_gb: i32,
73    #[serde(default, skip_serializing_if = "Option::is_none")]
74    pub max_tenants: Option<i32>,
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
78#[serde(rename_all = "snake_case")]
79pub enum CloudTenantStatus {
80    Pending,
81    Active,
82    Suspended,
83    Deleted,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct CloudTenantInfo {
88    pub id: String,
89    pub name: String,
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub subscription_id: Option<String>,
92    #[serde(default, skip_serializing_if = "Option::is_none")]
93    pub subscription_status: Option<SubscriptionStatus>,
94    #[serde(default, skip_serializing_if = "Option::is_none")]
95    pub app_id: Option<String>,
96    #[serde(default, skip_serializing_if = "Option::is_none")]
97    pub hostname: Option<String>,
98    #[serde(default, skip_serializing_if = "Option::is_none")]
99    pub region: Option<String>,
100    #[serde(default, skip_serializing_if = "Option::is_none")]
101    pub status: Option<CloudTenantStatus>,
102    #[serde(default, skip_serializing_if = "Option::is_none")]
103    pub plan: Option<CloudPlanInfo>,
104    #[serde(default)]
105    pub external_db_access: bool,
106    pub database_url: String,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
110pub struct CloudTenant {
111    pub id: String,
112    pub name: String,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub fly_app_name: Option<String>,
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub fly_hostname: Option<String>,
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub hostname: Option<String>,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
122pub struct CloudTenantStatusResponse {
123    pub status: String,
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub message: Option<String>,
126    #[serde(default, skip_serializing_if = "Option::is_none")]
127    pub app_url: Option<String>,
128    #[serde(default, skip_serializing_if = "Option::is_none")]
129    pub secrets_url: Option<String>,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct CloudTenantSecrets {
134    pub jwt_secret: String,
135    pub database_url: String,
136    pub internal_database_url: String,
137    pub app_url: String,
138    #[serde(default, skip_serializing_if = "Option::is_none")]
139    pub sync_token: Option<String>,
140    #[serde(default, skip_serializing_if = "Option::is_none")]
141    pub anthropic_api_key: Option<String>,
142    #[serde(default, skip_serializing_if = "Option::is_none")]
143    pub openai_api_key: Option<String>,
144    #[serde(default, skip_serializing_if = "Option::is_none")]
145    pub gemini_api_key: Option<String>,
146}
147
148#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
149pub struct SetExternalDbAccessRequest {
150    pub enabled: bool,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct ExternalDbAccessResponse {
155    pub tenant_id: systemprompt_identifiers::TenantId,
156    pub external_db_access: bool,
157    pub database_url: String,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct RotateCredentialsResponse {
162    pub status: String,
163    pub message: String,
164    pub internal_database_url: String,
165    pub external_database_url: String,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct RotateSyncTokenResponse {
170    pub sync_token: String,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct CloudEnterpriseLicenseInfo {
175    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, JsonSchema)]
208pub struct CloudStatusResponse {
209    pub status: String,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct SetSecretsRequest {
214    pub secrets: HashMap<String, String>,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
218pub struct CloudLogEntry {
219    pub timestamp: String,
220    pub message: String,
221    #[serde(default, skip_serializing_if = "Option::is_none")]
222    pub level: Option<String>,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct CloudLogsResponse {
227    pub logs: Vec<CloudLogEntry>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
231pub struct ListSecretsResponse {
232    pub keys: Vec<String>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
236pub struct SetCustomDomainRequest {
237    pub domain: String,
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
241pub struct DnsInstructions {
242    pub record_type: String,
243    pub host: String,
244    pub value: String,
245    pub ttl: u32,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
249pub struct CustomDomainResponse {
250    pub domain: String,
251    pub status: String,
252    pub verified: bool,
253    pub dns_target: String,
254    pub dns_instructions: DnsInstructions,
255    #[serde(default, skip_serializing_if = "Option::is_none")]
256    pub created_at: Option<String>,
257    #[serde(default, skip_serializing_if = "Option::is_none")]
258    pub verified_at: Option<String>,
259}
260
261pub type ApiResponse<T> = CloudApiResponse<T>;
262pub type ApiError = CloudApiError;
263pub type ApiErrorDetail = CloudApiErrorDetail;
264pub type UserInfo = CloudUserInfo;
265pub type CustomerInfo = CloudCustomerInfo;
266pub type PlanInfo = CloudPlanInfo;
267pub type Plan = CloudPlan;
268pub type TenantInfo = CloudTenantInfo;
269pub type Tenant = CloudTenant;
270pub type TenantStatus = CloudTenantStatusResponse;
271pub type TenantSecrets = CloudTenantSecrets;
272pub type ListResponse<T> = CloudListResponse<T>;
273pub type StatusResponse = CloudStatusResponse;
274pub type LogEntry = CloudLogEntry;
275pub type LogsResponse = CloudLogsResponse;
276pub type EnterpriseLicenseInfo = CloudEnterpriseLicenseInfo;