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