Skip to main content

systemprompt_cli/commands/cloud/
types.rs

1//! Serializable output DTOs for the `cloud` command group.
2//!
3//! Each type is the structured payload a cloud subcommand returns (status,
4//! login, tenant list/detail/create, secrets, deploy, sync, and related), used
5//! for both human rendering and `--json` output.
6//!
7//! Copyright (c) systemprompt.io — Business Source License 1.1.
8//! See <https://systemprompt.io> for licensing details.
9
10use chrono::{DateTime, Utc};
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13use systemprompt_identifiers::{CloudAppId, CloudUserId, TenantId};
14
15pub use systemprompt_manifest::profile::ProfileInfo;
16
17#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
18pub struct CredentialsInfo {
19    pub authenticated: bool,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub user_email: Option<String>,
22    pub token_expired: bool,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
26pub struct TenantStatusInfo {
27    pub id: TenantId,
28    pub name: String,
29    pub status: String,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub url: Option<String>,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub message: Option<String>,
34    pub configured_in_profile: bool,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
38pub struct CloudStatusOutput {
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub profile: Option<ProfileInfo>,
41    pub credentials: CredentialsInfo,
42    pub tenants: Vec<TenantStatusInfo>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
46pub struct TenantPlanInfo {
47    pub name: String,
48    pub memory_mb: i32,
49    pub volume_gb: i32,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
53pub struct LoginTenantInfo {
54    pub id: TenantId,
55    pub name: String,
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub subscription_status: Option<String>,
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub plan: Option<TenantPlanInfo>,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub region: Option<String>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub hostname: Option<String>,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
67pub struct LoginUserInfo {
68    pub id: CloudUserId,
69    pub email: String,
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub name: Option<String>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
75pub struct LoginCustomerInfo {
76    pub id: String,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
80pub struct LoginOutput {
81    pub user: LoginUserInfo,
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub customer: Option<LoginCustomerInfo>,
84    pub tenants: Vec<LoginTenantInfo>,
85    pub credentials_path: String,
86    pub tenants_path: String,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
90pub struct WhoamiOutput {
91    pub user_email: String,
92    pub api_url: String,
93    pub token_status: String,
94    pub authenticated_at: DateTime<Utc>,
95    pub local_profiles: usize,
96    pub cloud_tenants: usize,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
100pub struct LogoutOutput {
101    pub message: String,
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub credentials_path: Option<String>,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
107pub struct TenantSummary {
108    pub id: TenantId,
109    pub name: String,
110    pub tenant_type: String,
111    pub has_database: bool,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
115pub struct TenantListOutput {
116    pub tenants: Vec<TenantSummary>,
117    pub total: usize,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
121pub struct TenantDetailOutput {
122    pub id: TenantId,
123    pub name: String,
124    pub tenant_type: String,
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub app_id: Option<CloudAppId>,
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub hostname: Option<String>,
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub region: Option<String>,
131    pub has_database: bool,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
135pub struct RotateCredentialsOutput {
136    #[serde(rename = "tenant_id")]
137    pub tenant: TenantId,
138    pub status: String,
139    pub internal_database_url: String,
140    pub external_database_url: String,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
144pub struct ProfileSummary {
145    pub name: String,
146    pub has_secrets: bool,
147    pub is_active: bool,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
151pub struct ProfileListOutput {
152    pub profiles: Vec<ProfileSummary>,
153    pub total: usize,
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub active_profile: Option<String>,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
159pub struct SecretsOutput {
160    pub operation: String,
161    pub keys: Vec<String>,
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub rejected_keys: Option<Vec<String>>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
167pub struct RestartOutput {
168    pub tenant_name: String,
169    pub status: String,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
173pub struct DockerfileOutput {
174    pub content: String,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
178pub struct CancelSubscriptionOutput {
179    #[serde(rename = "tenant_id")]
180    pub tenant: TenantId,
181    pub tenant_name: String,
182    pub message: String,
183}