1pub mod admin;
7pub mod answers_crypto;
8pub mod bundle;
9pub mod bundle_source;
10pub mod capabilities;
11pub mod card_setup;
12pub mod cli_args;
13pub mod cli_commands;
14pub mod cli_helpers;
15pub mod cli_i18n;
16pub mod config_envelope;
17pub mod deployment_targets;
18pub mod discovery;
19pub mod engine;
20pub mod flow;
21pub mod gtbundle;
22pub mod plan;
23pub mod platform_setup;
24pub mod reload;
25pub mod secret_name;
26pub mod secrets;
27pub mod setup_input;
28pub mod setup_to_formspec;
29pub mod webhook;
30
31pub mod qa {
32 pub mod bridge;
35 pub mod persist;
36 pub mod wizard;
37}
38
39pub use bundle_source::BundleSource;
40pub use engine::SetupEngine;
41pub use plan::{SetupMode, SetupPlan, SetupStep, SetupStepKind};
42
43pub fn version() -> &'static str {
45 env!("CARGO_PKG_VERSION")
46}
47
48pub fn resolve_env(override_env: Option<&str>) -> String {
52 override_env
53 .map(|v| v.to_string())
54 .or_else(|| std::env::var("GREENTIC_ENV").ok())
55 .unwrap_or_else(|| "dev".to_string())
56}
57
58pub fn canonical_secret_uri(
60 env: &str,
61 tenant: &str,
62 team: Option<&str>,
63 provider: &str,
64 key: &str,
65) -> String {
66 let team_segment = canonical_team(team);
67 let provider_segment = if provider.is_empty() {
68 "messaging".to_string()
69 } else {
70 provider.to_string()
71 };
72 let normalized_key = secret_name::canonical_secret_name(key);
73 format!("secrets://{env}/{tenant}/{team_segment}/{provider_segment}/{normalized_key}")
74}
75
76fn canonical_team(team: Option<&str>) -> &str {
80 match team
81 .map(|v| v.trim())
82 .filter(|t| !t.is_empty() && !t.eq_ignore_ascii_case("default"))
83 {
84 Some(v) => v,
85 None => "_",
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn version_is_correct() {
95 assert!(version().starts_with("0.4"));
96 }
97
98 #[test]
99 fn secret_uri_basic() {
100 let uri = canonical_secret_uri("dev", "demo", None, "messaging-telegram", "bot_token");
101 assert_eq!(uri, "secrets://dev/demo/_/messaging-telegram/bot_token");
102 }
103
104 #[test]
105 fn secret_uri_with_team() {
106 let uri = canonical_secret_uri("dev", "acme", Some("ops"), "state-redis", "redis_url");
107 assert_eq!(uri, "secrets://dev/acme/ops/state-redis/redis_url");
108 }
109
110 #[test]
111 fn secret_uri_default_team_becomes_wildcard() {
112 let uri = canonical_secret_uri(
113 "dev",
114 "demo",
115 Some("default"),
116 "messaging-slack",
117 "bot_token",
118 );
119 assert_eq!(uri, "secrets://dev/demo/_/messaging-slack/bot_token");
120 }
121}