systemprompt_cloud/profile_authoring/
cloud_builder.rs1use systemprompt_identifiers::TenantId;
7use systemprompt_models::profile::{
8 ProviderRegistry, SecretsConfig, SecretsSource, SecretsValidationMode, TrustedIssuer,
9};
10use systemprompt_models::services::SystemAdminConfig;
11use systemprompt_models::{
12 CloudConfig, CloudValidationMode, ContentNegotiationConfig, ExtensionsConfig, PathsConfig,
13 Profile, ProfileDatabaseConfig, ProfileType, RateLimitsConfig, SecurityHeadersConfig,
14 ServerConfig, SiteConfig,
15};
16
17use super::{cloud_runtime_config, generate_display_name, security_config, webhook_governance};
18use crate::constants::{container, profile as consts};
19
20#[derive(Debug)]
21pub struct CloudProfileBuilder {
22 name: String,
23 tenant_id: Option<TenantId>,
24 external_url: Option<String>,
25 external_db_access: bool,
26 secrets_path: Option<String>,
27 trusted_issuers: Vec<TrustedIssuer>,
28}
29
30impl CloudProfileBuilder {
31 pub fn new(name: impl Into<String>) -> Self {
32 Self {
33 name: name.into(),
34 tenant_id: None,
35 external_url: None,
36 external_db_access: false,
37 secrets_path: None,
38 trusted_issuers: Vec::new(),
39 }
40 }
41
42 #[must_use]
43 pub fn with_trusted_issuer(mut self, issuer: TrustedIssuer) -> Self {
44 self.trusted_issuers.push(issuer);
45 self
46 }
47
48 #[must_use]
49 pub fn with_tenant_id(mut self, tenant_id: TenantId) -> Self {
50 self.tenant_id = Some(tenant_id);
51 self
52 }
53
54 #[must_use]
55 pub fn with_external_url(mut self, url: impl Into<String>) -> Self {
56 self.external_url = Some(url.into());
57 self
58 }
59
60 #[must_use]
61 pub const fn with_external_db_access(mut self, enabled: bool) -> Self {
62 self.external_db_access = enabled;
63 self
64 }
65
66 #[must_use]
67 pub fn with_secrets_path(mut self, path: impl Into<String>) -> Self {
68 self.secrets_path = Some(path.into());
69 self
70 }
71
72 #[must_use]
73 pub fn build(self) -> Profile {
74 let display_name = generate_display_name(&self.name);
75 let external = self
76 .external_url
77 .unwrap_or_else(|| consts::DEFAULT_CLOUD_URL.to_owned());
78 let internal_url = format!("http://localhost:{}", consts::DEFAULT_PORT);
79
80 Profile {
81 name: self.name,
82 display_name,
83 target: ProfileType::Cloud,
84 site: SiteConfig {
85 name: "systemprompt.io".to_owned(),
86 github_link: None,
87 },
88 database: ProfileDatabaseConfig {
89 db_type: consts::DEFAULT_DB_TYPE.to_owned(),
90 external_db_access: self.external_db_access,
91 pool: None,
92 },
93 server: ServerConfig {
94 host: consts::CLOUD_HOST.to_owned(),
95 port: consts::DEFAULT_PORT,
96 api_server_url: external.clone(),
97 api_internal_url: internal_url.clone(),
98 api_external_url: external.clone(),
99 use_https: true,
100 cors_allowed_origins: vec![external],
101 content_negotiation: ContentNegotiationConfig::default(),
102 security_headers: SecurityHeadersConfig::default(),
103 instance_id: None,
104 max_concurrent_streams: systemprompt_models::config::DEFAULT_MAX_CONCURRENT_STREAMS,
105 trusted_proxies: Vec::new(),
106 },
107 paths: PathsConfig {
108 system: container::APP.to_owned(),
109 services: container::SERVICES.to_owned(),
110 bin: container::BIN.to_owned(),
111 storage: Some(container::STORAGE.to_owned()),
112 geoip_database: None,
113 web_path: Some(container::WEB.to_owned()),
114 },
115 security: security_config(consts::CLOUD_ISSUER, self.trusted_issuers),
116 rate_limits: RateLimitsConfig::default(),
117 runtime: cloud_runtime_config(),
118 cloud: Some(CloudConfig {
119 tenant_id: self.tenant_id,
120 validation: CloudValidationMode::Strict,
121 }),
122 secrets: Some(SecretsConfig {
123 secrets_path: self.secrets_path.unwrap_or_else(String::new),
124 validation: SecretsValidationMode::Strict,
125 source: SecretsSource::Env,
126 }),
127 extensions: ExtensionsConfig::default(),
128 providers: ProviderRegistry::default(),
129 gateway: None,
130 governance: Some(webhook_governance(&internal_url)),
131 system_admin: SystemAdminConfig {
132 username: "admin".to_owned(),
133 },
134 }
135 }
136}