Skip to main content

systemprompt_cloud/profile_authoring/
mod.rs

1//! Profile construction for local and cloud deployment targets.
2//!
3//! [`LocalProfileBuilder`] and [`CloudProfileBuilder`] encode the differing
4//! defaults for each target (host, URLs, paths, security, runtime, and
5//! validation modes) so callers only supply the tenant-specific fields.
6//! Construction is pure — no prompting and no filesystem writes; interactive
7//! collection of the inputs stays in the CLI.
8//!
9//! Copyright (c) systemprompt.io — Business Source License 1.1.
10//! See <https://systemprompt.io> for licensing details.
11
12mod cloud_builder;
13mod local_builder;
14
15pub use cloud_builder::CloudProfileBuilder;
16pub use local_builder::LocalProfileBuilder;
17
18use systemprompt_models::auth::JwtAudience;
19use systemprompt_models::profile::{
20    AuthzConfig, AuthzHookConfig, AuthzMode, GovernanceConfig, TrustedIssuer,
21    default_resource_audiences,
22};
23use systemprompt_models::{Environment, LogLevel, OutputFormat, RuntimeConfig, SecurityConfig};
24
25use crate::constants::profile as consts;
26
27#[must_use]
28pub fn generate_display_name(name: &str) -> String {
29    match name.to_lowercase().as_str() {
30        "dev" | "development" => "Development".to_owned(),
31        "prod" | "production" => "Production".to_owned(),
32        "staging" | "stage" => "Staging".to_owned(),
33        "test" | "testing" => "Test".to_owned(),
34        "local" => "Local Development".to_owned(),
35        "cloud" => "Cloud".to_owned(),
36        _ => capitalize_first(name),
37    }
38}
39
40fn capitalize_first(name: &str) -> String {
41    let mut chars = name.chars();
42    chars.next().map_or_else(String::new, |first| {
43        first.to_uppercase().chain(chars).collect()
44    })
45}
46
47fn webhook_governance(api_internal_url: &str) -> GovernanceConfig {
48    GovernanceConfig {
49        authz: Some(AuthzConfig {
50            hook: AuthzHookConfig {
51                mode: AuthzMode::Webhook,
52                url: Some(format!("{api_internal_url}/api/public/govern/authz")),
53                timeout_ms: 500,
54                acknowledgement: None,
55            },
56        }),
57    }
58}
59
60fn security_config(issuer: &str, trusted_issuers: Vec<TrustedIssuer>) -> SecurityConfig {
61    SecurityConfig {
62        issuer: issuer.to_owned(),
63        access_token_expiration: consts::ACCESS_TOKEN_EXPIRATION,
64        refresh_token_expiration: consts::REFRESH_TOKEN_EXPIRATION,
65        audiences: JwtAudience::standard(),
66        allowed_resource_audiences: default_resource_audiences(),
67        allow_registration: true,
68        signing_key_path: std::path::PathBuf::from("signing_key.pem"),
69        trusted_issuers,
70        id_jag_ttl_secs: systemprompt_models::profile::DEFAULT_ID_JAG_TTL_SECS,
71    }
72}
73
74const fn local_runtime_config() -> RuntimeConfig {
75    RuntimeConfig {
76        environment: Environment::Development,
77        log_level: LogLevel::Verbose,
78        output_format: OutputFormat::Text,
79        no_color: false,
80        non_interactive: false,
81    }
82}
83
84const fn cloud_runtime_config() -> RuntimeConfig {
85    RuntimeConfig {
86        environment: Environment::Production,
87        log_level: LogLevel::Normal,
88        output_format: OutputFormat::Json,
89        no_color: true,
90        non_interactive: true,
91    }
92}