Pass GlobalConfig directly to config template
Adds Display impls for SecretString ("[secret]") and Executor, then
replaces the hand-built rows vec with a direct GlobalConfig field on
ConfigTemplate. The handler shrinks to two lines; layout logic lives
in the template where it belongs.
change
commit 682a07cf399f62e266c1ca0f820f70f2e526d605
author Claude <noreply@anthropic.com>
date
parent d83a5cee
diff --git a/quire-server/src/ci/run.rs b/quire-server/src/ci/run.rs
index e5c08b1..bbd1806 100644
--- a/quire-server/src/ci/run.rs
+++ b/quire-server/src/ci/run.rs
@@ -27,6 +27,14 @@ pub enum Executor {
     Process,
 }
 
+impl std::fmt::Display for Executor {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::Process => f.write_str("process"),
+        }
+    }
+}
+
 /// Access to CI runs for a single repo.
 ///
 /// Owns the database path, repo name, and base directory for run
diff --git a/quire-server/src/quire/web/handlers.rs b/quire-server/src/quire/web/handlers.rs
index a1addd1..b0c2d4f 100644
--- a/quire-server/src/quire/web/handlers.rs
+++ b/quire-server/src/quire/web/handlers.rs
@@ -281,37 +281,9 @@ pub async fn run_detail(
 }
 
 pub async fn config(State(quire): State<Quire>) -> Response {
-    let cfg = &quire.config;
-    let mut rows: Vec<(String, String)> = Vec::new();
-
-    rows.push(("port".into(), cfg.port.to_string()));
-    rows.push((
-        "ci.executor".into(),
-        format!("{:?}", cfg.ci.executor).to_lowercase(),
-    ));
-
-    match &cfg.sentry {
-        Some(s) => rows.push(("sentry.dsn".into(), s.dsn.to_string())),
-        None => rows.push(("sentry".into(), "disabled".into())),
-    }
-
-    match &cfg.github.mirror_token {
-        Some(t) => rows.push(("github.mirror-token".into(), t.to_string())),
-        None => rows.push(("github.mirror-token".into(), "not set".into())),
-    }
-
-    let mut secret_keys: Vec<&String> = cfg.secrets.keys().collect();
-    secret_keys.sort();
-    for key in secret_keys {
-        rows.push((
-            format!("secrets.{key}"),
-            cfg.secrets[key].to_string(),
-        ));
-    }
-
     let tmpl = ConfigTemplate {
         crumbs: vec![Crumb::new("config")],
-        rows,
+        config: quire.config.clone(),
     };
     render(&tmpl)
 }
diff --git a/quire-server/src/quire/web/templates.rs b/quire-server/src/quire/web/templates.rs
index f145331..e39339f 100644
--- a/quire-server/src/quire/web/templates.rs
+++ b/quire-server/src/quire/web/templates.rs
@@ -233,13 +233,19 @@ impl DetailShEvent {
 #[template(path = "config.html")]
 pub struct ConfigTemplate {
     pub crumbs: Vec<Crumb>,
-    pub rows: Vec<(String, String)>,
+    pub config: crate::GlobalConfig,
 }
 
 impl ConfigTemplate {
     pub fn version(&self) -> &'static str {
         pkg_version()
     }
+
+    pub fn sorted_secrets(&self) -> Vec<(&String, &quire_core::secret::SecretString)> {
+        let mut pairs: Vec<_> = self.config.secrets.iter().collect();
+        pairs.sort_by_key(|(k, _)| *k);
+        pairs
+    }
 }
 
 // ── Error ──────────────────────────────────────────────────────────
diff --git a/quire-server/templates/config.html b/quire-server/templates/config.html
index b18f46c..a64367d 100644
--- a/quire-server/templates/config.html
+++ b/quire-server/templates/config.html
@@ -31,11 +31,20 @@
 <h2 class="ci-heading">config</h2>
 <table class="ci-table">
   <tbody>
-    {% for (key, value) in rows %}
-    <tr>
-      <th>{{ key }}</th>
-      <td>{{ value }}</td>
-    </tr>
+    <tr><th>port</th><td>{{ config.port }}</td></tr>
+    <tr><th>ci.executor</th><td>{{ config.ci.executor }}</td></tr>
+    {% if let Some(sentry) = config.sentry %}
+    <tr><th>sentry.dsn</th><td>{{ sentry.dsn }}</td></tr>
+    {% else %}
+    <tr><th>sentry</th><td class="empty">disabled</td></tr>
+    {% endif %}
+    {% if let Some(token) = config.github.mirror_token %}
+    <tr><th>github.mirror-token</th><td>{{ token }}</td></tr>
+    {% else %}
+    <tr><th>github.mirror-token</th><td class="empty">not set</td></tr>
+    {% endif %}
+    {% for (key, value) in sorted_secrets() %}
+    <tr><th>secrets.{{ key }}</th><td>{{ value }}</td></tr>
     {% endfor %}
   </tbody>
 </table>