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
31#[cfg(feature = "ui")]
32pub mod ui;
33
34pub mod qa {
35 pub mod bridge;
38 pub mod persist;
39 pub mod prompts;
40 pub mod shared_questions;
41 pub mod wizard;
42}
43
44pub use bundle_source::BundleSource;
45pub use engine::SetupEngine;
46pub use plan::{SetupMode, SetupPlan, SetupStep, SetupStepKind};
47
48pub use qa::wizard::{
50 ProviderFormSpec, SHARED_QUESTION_IDS, SharedQuestionsResult, build_provider_form_specs,
51 collect_shared_questions, prompt_shared_questions, run_qa_setup_with_shared,
52};
53
54pub fn version() -> &'static str {
56 env!("CARGO_PKG_VERSION")
57}
58
59pub fn resolve_env(override_env: Option<&str>) -> String {
63 override_env
64 .map(|v| v.to_string())
65 .or_else(|| std::env::var("GREENTIC_ENV").ok())
66 .unwrap_or_else(|| "dev".to_string())
67}
68
69pub fn canonical_secret_uri(
71 env: &str,
72 tenant: &str,
73 team: Option<&str>,
74 provider: &str,
75 key: &str,
76) -> String {
77 let team_segment = canonical_team(team);
78 let provider_segment = if provider.is_empty() {
79 "messaging".to_string()
80 } else {
81 provider.to_string()
82 };
83 let normalized_key = secret_name::canonical_secret_name(key);
84 format!("secrets://{env}/{tenant}/{team_segment}/{provider_segment}/{normalized_key}")
85}
86
87fn canonical_team(team: Option<&str>) -> &str {
91 match team
92 .map(|v| v.trim())
93 .filter(|t| !t.is_empty() && !t.eq_ignore_ascii_case("default"))
94 {
95 Some(v) => v,
96 None => "_",
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn version_is_correct() {
106 assert!(version().starts_with("0.4"));
107 }
108
109 #[test]
110 fn secret_uri_basic() {
111 let uri = canonical_secret_uri("dev", "demo", None, "messaging-telegram", "bot_token");
112 assert_eq!(uri, "secrets://dev/demo/_/messaging-telegram/bot_token");
113 }
114
115 #[test]
116 fn secret_uri_with_team() {
117 let uri = canonical_secret_uri("dev", "acme", Some("ops"), "state-redis", "redis_url");
118 assert_eq!(uri, "secrets://dev/acme/ops/state-redis/redis_url");
119 }
120
121 #[test]
122 fn secret_uri_default_team_becomes_wildcard() {
123 let uri = canonical_secret_uri(
124 "dev",
125 "demo",
126 Some("default"),
127 "messaging-slack",
128 "bot_token",
129 );
130 assert_eq!(uri, "secrets://dev/demo/_/messaging-slack/bot_token");
131 }
132}