Skip to main content

gobby_code/setup/
types.rs

1use super::contracts::DEFAULT_SCHEMA;
2use serde::{Deserialize, Serialize};
3
4#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
5pub struct Redacted(Option<String>);
6
7impl Redacted {
8    pub fn new(value: Option<String>) -> Self {
9        Self(value)
10    }
11
12    pub fn as_deref(&self) -> Option<&str> {
13        self.0.as_deref()
14    }
15
16    pub fn is_some(&self) -> bool {
17        self.0.is_some()
18    }
19
20    pub fn clone_inner(&self) -> Option<String> {
21        self.0.clone()
22    }
23}
24
25impl From<Option<String>> for Redacted {
26    fn from(value: Option<String>) -> Self {
27        Self::new(value)
28    }
29}
30
31impl std::fmt::Debug for Redacted {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        match self.0 {
34            Some(_) => f.write_str("<redacted>"),
35            None => f.write_str("None"),
36        }
37    }
38}
39
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
41pub struct StandaloneSetupRequest {
42    pub standalone: bool,
43    /// Setup-only PostgreSQL URL. It is passed to the live connection path,
44    /// redacted from `Debug`, and never persisted to JSON output.
45    #[serde(skip_serializing, default)]
46    pub database_url: Redacted,
47    pub no_services: bool,
48    pub overwrite_code_index: bool,
49    pub schema: String,
50    pub embedding_provider: Option<String>,
51    pub embedding_api_base: Option<String>,
52    pub embedding_model: Option<String>,
53    pub embedding_query_prefix: Option<String>,
54    pub embedding_vector_dim: Option<usize>,
55    /// Setup-only embedding secret. It is redacted from `Debug`; standalone
56    /// setup persists it only to the user's local gcore.yaml.
57    #[serde(skip_serializing, default)]
58    pub embedding_api_key: Redacted,
59    pub falkordb_host: Option<String>,
60    pub falkordb_port: Option<u16>,
61    /// Setup-only FalkorDB secret. It is used during provisioning, redacted
62    /// from `Debug`, and never persisted to JSON output.
63    #[serde(skip_serializing, default)]
64    pub falkordb_password: Redacted,
65    pub qdrant_url: Option<String>,
66}
67
68impl StandaloneSetupRequest {
69    pub fn new(standalone: bool, database_url: Option<String>, schema: Option<String>) -> Self {
70        Self {
71            standalone,
72            database_url: Redacted::new(database_url),
73            no_services: false,
74            overwrite_code_index: false,
75            schema: schema.unwrap_or_else(|| DEFAULT_SCHEMA.to_string()),
76            embedding_provider: None,
77            embedding_api_base: None,
78            embedding_model: None,
79            embedding_query_prefix: None,
80            embedding_vector_dim: None,
81            embedding_api_key: Redacted::default(),
82            falkordb_host: None,
83            falkordb_port: None,
84            falkordb_password: Redacted::default(),
85            qdrant_url: None,
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn standalone_setup_request_debug_redacts_secrets() {
96        let mut request = StandaloneSetupRequest::new(
97            true,
98            Some("postgres://user:secret-db@localhost/gobby".to_string()),
99            None,
100        );
101        request.embedding_api_key = Some("secret-embedding-key".to_string()).into();
102        request.falkordb_password = Some("secret-falkor-password".to_string()).into();
103
104        let debug = format!("{request:?}");
105
106        assert!(debug.contains("<redacted>"));
107        assert!(!debug.contains("secret-db"));
108        assert!(!debug.contains("secret-embedding-key"));
109        assert!(!debug.contains("secret-falkor-password"));
110    }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
114pub struct StandaloneServicesStatus {
115    pub provisioned: bool,
116    pub compose_file: Option<String>,
117    pub health_checks: Vec<String>,
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
121pub struct StandaloneEmbeddingStatus {
122    pub provider: String,
123    pub api_base: String,
124    pub model: String,
125    pub query_prefix: Option<String>,
126    pub vector_dim: usize,
127    pub api_key_present: bool,
128    pub api_key_fingerprint: Option<String>,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
132pub struct StandaloneFailure {
133    pub name: String,
134    pub reason: String,
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
138pub struct StandaloneSetupStatus {
139    pub namespace: String,
140    pub schema: String,
141    pub created: Vec<String>,
142    pub skipped: Vec<String>,
143    pub failed: Vec<StandaloneFailure>,
144    pub config_file: Option<String>,
145    pub services: Option<StandaloneServicesStatus>,
146    pub embedding: Option<StandaloneEmbeddingStatus>,
147}