kitgit

tirbofish/kitgit · diff

03480d9 · Thribhu K

feat: polish signed commit verification badges

Verified

diff --git a/src/web/routes.rs b/src/web/routes.rs
index c080f6f..66cf2f9 100644
--- a/src/web/routes.rs
+++ b/src/web/routes.rs
@@ -2491,6 +2491,7 @@ async fn commit_view(
     c: git::CommitInfo,
     extracted: Option<(String, Vec<u8>)>,
 ) -> CommitView {
+    let signed = extracted.is_some();
     let verification = match extracted {
         Some((sig, payload)) => {
             git::verify_commit_signature(
@@ -2525,6 +2526,7 @@ async fn commit_view(
         author: c.author,
         email: c.email,
         time: c.time,
+        signed,
         verified,
         verify_kind,
         verify_fingerprint,
diff --git a/src/web/templates.rs b/src/web/templates.rs
index a2932d4..2f5c47a 100644
--- a/src/web/templates.rs
+++ b/src/web/templates.rs
@@ -65,6 +65,8 @@ pub struct CommitView {
     pub author: String,
     pub email: String,
     pub time: i64,
+    /// True when a signature blob was present on the commit (SSH or GPG).
+    pub signed: bool,
     pub verified: bool,
     pub verify_kind: String,
     pub verify_fingerprint: String,
@@ -72,6 +74,16 @@ pub struct CommitView {
     pub verified_at: String,
 }
 
+impl CommitView {
+    pub fn verify_kind_label(&self) -> &'static str {
+        match self.verify_kind.as_str() {
+            "gpg" => "GPG",
+            "ssh" => "SSH",
+            _ => "Unknown",
+        }
+    }
+}
+
 pub struct CollaboratorView {
     pub user: User,
     pub role: String,
diff --git a/static/brand.css b/static/brand.css
index d50db11..ac49db9 100644
--- a/static/brand.css
+++ b/static/brand.css
@@ -1467,6 +1467,20 @@ html.kg-dark .kg-codeview .punctuation { color: #b0b0b0; }
   cursor: pointer;
 }
 
+.kg-badge--unverified {
+  color: var(--kg-muted);
+  border-color: var(--kg-line-strong);
+  background: transparent;
+  text-transform: none;
+  letter-spacing: 0.02em;
+  font-weight: 600;
+  cursor: default;
+}
+
+.kg-verify .kg-badge--unverified {
+  cursor: pointer;
+}
+
 .kg-verify {
   position: relative;
   display: inline-block;
@@ -1494,6 +1508,12 @@ html.kg-dark .kg-codeview .punctuation { color: #b0b0b0; }
   box-shadow: 0 8px 24px color-mix(in srgb, var(--kg-fg) 12%, transparent);
 }
 
+.kg-verify__row {
+  margin: 0 0 0.35rem;
+  font-size: 0.8125rem;
+  line-height: 1.4;
+}
+
 .kg-verify__fp {
   margin: 0 0 0.35rem;
   font-size: 0.8125rem;
@@ -1505,6 +1525,29 @@ html.kg-dark .kg-codeview .punctuation { color: #b0b0b0; }
   font-size: 0.75rem;
 }
 
+.kg-verify__panel a {
+  color: inherit;
+  text-decoration: underline;
+}
+
+.kg-signing-hint {
+  margin: 1rem 0 0;
+  padding: var(--kg-space-3);
+  border: 1px dashed var(--kg-line-strong);
+  background: color-mix(in srgb, var(--kg-fg) 3%, transparent);
+  font-size: 0.875rem;
+  line-height: 1.5;
+}
+
+.kg-signing-hint pre {
+  margin: 0.5rem 0 0;
+  padding: var(--kg-space-2);
+  overflow-x: auto;
+  font-size: 0.75rem;
+  background: var(--kg-bg);
+  border: 1px solid var(--kg-line);
+}
+
 .kg-key-row {
   align-items: flex-start;
 }
diff --git a/templates/keys_settings.html b/templates/keys_settings.html
index ecd9ef5..64d02b4 100644
--- a/templates/keys_settings.html
+++ b/templates/keys_settings.html
@@ -17,7 +17,7 @@
   {% endif %}
 
   <span class="kg-kicker" style="margin-top:1.5rem">SSH keys</span>
-  <p class="kg-muted">Authentication keys let you push/pull over SSH. Signing keys verify signed commits.</p>
+  <p class="kg-muted">Authentication keys let you push/pull over SSH. Signing keys verify signed commits on kitgit (Verified badge).</p>
   {% if !keys.is_empty() %}
     <ul class="kg-list">
       {% for key in keys %}
@@ -70,6 +70,14 @@
     </div>
   </form>
 
+  <div class="kg-signing-hint">
+    <strong>Sign commits with SSH</strong>
+    <p class="kg-muted" style="margin:0.35rem 0 0">Add the public key above with usage <em>Signing</em> or <em>Authentication &amp; Signing</em>, then configure git locally. Author email must match a verified email on your account.</p>
+    <pre>git config --global gpg.format ssh
+git config --global user.signingkey ~/.ssh/id_ed25519.pub
+git config --global commit.gpgsign true</pre>
+  </div>
+
   <span class="kg-kicker" style="margin-top:2.5rem">GPG keys</span>
   <p class="kg-muted">Used for commit verification. Vigilant mode flags unsigned commits on your profile.</p>
   {% if !gpg_keys.is_empty() %}
@@ -104,5 +112,12 @@
       <button class="kg-btn" type="submit">add</button>
     </div>
   </form>
+
+  <div class="kg-signing-hint">
+    <strong>Sign commits with GPG</strong>
+    <p class="kg-muted" style="margin:0.35rem 0 0">Paste your public key above, then point git at the key id. Author email must match a verified email on your account.</p>
+    <pre>git config --global user.signingkey YOUR_KEY_ID
+git config --global commit.gpgsign true</pre>
+  </div>
 </section>
 {% endblock %}
diff --git a/templates/partials/branch_bar.html b/templates/partials/branch_bar.html
index 5069541..e5210d2 100644
--- a/templates/partials/branch_bar.html
+++ b/templates/partials/branch_bar.html
@@ -12,18 +12,8 @@
         {{ c.short_id }}
       </a>
       <a class="kg-branchbar__msg" href="/{{ owner.username }}/{{ repo.name }}/commit/{{ c.id }}" title="View commit">{{ c.message }}</a>
-      {% if c.verified %}
-      <details class="kg-verify">
-        <summary class="kg-badge kg-badge--verified">Verified</summary>
-        <div class="kg-verify__panel" role="dialog" aria-label="Commit signature">
-          <p class="kg-verify__fp">
-            <strong>{{ c.verify_fingerprint_label }}:</strong>
-            <code>{{ c.verify_fingerprint }}</code>
-          </p>
-          <p class="kg-meta">Verified on {{ c.verified_at }}</p>
-        </div>
-      </details>
-      {% endif %}
+      {% let show_unverified = false %}
+      {% include "partials/verified_badge.html" %}
     </div>
     {% endif %}
   </div>
diff --git a/templates/partials/verified_badge.html b/templates/partials/verified_badge.html
index d448c5c..6697dca 100644
--- a/templates/partials/verified_badge.html
+++ b/templates/partials/verified_badge.html
@@ -1,12 +1,24 @@
-{% if let Some(v) = verification %}
+{# Expects CommitView as `c`. Optional: `show_unverified` (bool) — show Unverified for unsigned too. #}
+{% if c.verified %}
 <details class="kg-verify">
   <summary class="kg-badge kg-badge--verified">Verified</summary>
   <div class="kg-verify__panel" role="dialog" aria-label="Commit signature">
+    <p class="kg-verify__row"><strong>Type:</strong> {{ c.verify_kind_label() }}</p>
     <p class="kg-verify__fp">
-      <strong>{{ v.fingerprint_label() }}:</strong>
-      <code>{{ v.fingerprint }}</code>
+      <strong>{{ c.verify_fingerprint_label }}:</strong>
+      <code>{{ c.verify_fingerprint }}</code>
     </p>
-    <p class="kg-meta">Verified on {{ v.verified_at }}</p>
+    <p class="kg-meta">Verified on {{ c.verified_at }}</p>
   </div>
 </details>
+{% else if c.signed %}
+<details class="kg-verify">
+  <summary class="kg-badge kg-badge--unverified">Unverified</summary>
+  <div class="kg-verify__panel" role="dialog" aria-label="Commit signature">
+    <p class="kg-verify__row">Signature present but could not be verified.</p>
+    <p class="kg-meta">Add a matching signing SSH or GPG key under <a href="/settings/keys">Settings → SSH / GPG</a>. The commit author email must match a verified email on that account.</p>
+  </div>
+</details>
+{% else if show_unverified %}
+<span class="kg-badge kg-badge--unverified" title="Commit is not signed">Unverified</span>
 {% endif %}
diff --git a/templates/pull_view.html b/templates/pull_view.html
index 92b3f55..cf49565 100644
--- a/templates/pull_view.html
+++ b/templates/pull_view.html
@@ -98,18 +98,8 @@
           <span>
             <a href="/{{ owner.username }}/{{ repo.name }}/commits" title="View commits"><code>{{ c.short_id }}</code></a>
             <a href="/{{ owner.username }}/{{ repo.name }}/commit/{{ c.id }}">{{ c.message }}</a>
-            {% if c.verified %}
-            <details class="kg-verify">
-              <summary class="kg-badge kg-badge--verified">Verified</summary>
-              <div class="kg-verify__panel" role="dialog" aria-label="Commit signature">
-                <p class="kg-verify__fp">
-                  <strong>{{ c.verify_fingerprint_label }}:</strong>
-                  <code>{{ c.verify_fingerprint }}</code>
-                </p>
-                <p class="kg-meta">Verified on {{ c.verified_at }}</p>
-              </div>
-            </details>
-            {% endif %}
+            {% let show_unverified = false %}
+            {% include "partials/verified_badge.html" %}
           </span>
           <span class="kg-meta">{{ c.author }}</span>
         </li>
diff --git a/templates/repo_commit.html b/templates/repo_commit.html
index 0b1244e..9e5199d 100644
--- a/templates/repo_commit.html
+++ b/templates/repo_commit.html
@@ -15,18 +15,9 @@
   <p><code>{{ commit.id }}</code></p>
   <p class="kg-title">
     {{ message_html|safe }}
-    {% if commit.verified %}
-    <details class="kg-verify">
-      <summary class="kg-badge kg-badge--verified">Verified</summary>
-      <div class="kg-verify__panel" role="dialog" aria-label="Commit signature">
-        <p class="kg-verify__fp">
-          <strong>{{ commit.verify_fingerprint_label }}:</strong>
-          <code>{{ commit.verify_fingerprint }}</code>
-        </p>
-        <p class="kg-meta">Verified on {{ commit.verified_at }}</p>
-      </div>
-    </details>
-    {% endif %}
+    {% let c = commit %}
+    {% let show_unverified = true %}
+    {% include "partials/verified_badge.html" %}
   </p>
   <p class="kg-meta">{{ commit.author }} &lt;{{ commit.email }}&gt; · {{ commit.time }}</p>
 
diff --git a/templates/repo_commits.html b/templates/repo_commits.html
index a763fd2..25faab0 100644
--- a/templates/repo_commits.html
+++ b/templates/repo_commits.html
@@ -31,18 +31,8 @@
             <code>{{ c.short_id }}</code>
           </a>
           <a href="/{{ owner.username }}/{{ repo.name }}/commit/{{ c.id }}">{{ c.message }}</a>
-          {% if c.verified %}
-          <details class="kg-verify">
-            <summary class="kg-badge kg-badge--verified">Verified</summary>
-            <div class="kg-verify__panel" role="dialog" aria-label="Commit signature">
-              <p class="kg-verify__fp">
-                <strong>{{ c.verify_fingerprint_label }}:</strong>
-                <code>{{ c.verify_fingerprint }}</code>
-              </p>
-              <p class="kg-meta">Verified on {{ c.verified_at }}</p>
-            </div>
-          </details>
-          {% endif %}
+          {% let show_unverified = false %}
+          {% include "partials/verified_badge.html" %}
           <span class="kg-muted"> — {{ c.author }}</span>
         </span>
         <span class="kg-meta">{{ c.time }}</span>
diff --git a/templates/repo_diff.html b/templates/repo_diff.html
index 129dab6..4d32b65 100644
--- a/templates/repo_diff.html
+++ b/templates/repo_diff.html
@@ -21,6 +21,9 @@
   </p>
   <p class="kg-title">
     <a href="/{{ owner.username }}/{{ repo.name }}/commit/{{ commit.id }}">{{ commit.message }}</a>
+    {% let c = commit %}
+    {% let show_unverified = true %}
+    {% include "partials/verified_badge.html" %}
   </p>
 
   {{ diff_html|safe }}