markdown · 4855 bytes Raw Blame History

Deploy: GPG keys + commit signature verification (S51)

S51 ships the GPG-keys storage + the verification orchestrator

  • the Verified-badge rendering + a bulk-backfill admin command, all in one feature-branch merge to trunk. The migrations are additive and the rendering paths fall back to "unsigned" (no badge) on cache miss, so the rollout is safe to do in-band — no maintenance window required.

Pre-deploy

  1. Note the currently-deployed ldd /opt/shithub/bin/shithubd output. shithub uses pure-Go OpenPGP via github.com/ProtonMail/go-crypto; no new dynamic deps are expected. Diffing post-deploy confirms.

    ssh root@shithub.sh "ldd /opt/shithub/bin/shithubd" > /tmp/ldd-pre.txt
    
  2. Capture migration status as a baseline:

    ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate status" \
      > /tmp/migrate-pre.txt
    

Deploy

  1. Apply migrations. Three new versions land:

    • 0068_user_gpg_keys.sql — primary keys table
    • 0069_user_gpg_subkeys.sql — subkey fingerprint reverse-lookup
    • 0070_commit_verification_cache.sql — verification result cache
    ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate up"
    ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate status"
    

    migrate status should report all three at version applied.

  2. Quick sanity-check the three new tables exist and are empty:

    ssh root@shithub.sh "sudo -u shithub psql -d shithub -c '
      SELECT count(*) FROM user_gpg_keys;
      SELECT count(*) FROM user_gpg_subkeys;
      SELECT count(*) FROM commit_verification_cache;'"
    

    Expect 0 / 0 / 0.

  3. Rolling-restart shithubd. The deploy unit drops one replica at a time; the health endpoint reports 200 once a replica has finished its startup migration check.

    ssh root@shithub.sh "sudo systemctl restart shithubd@*"
    
  4. Confirm the gpg-keys capability landed:

    curl -fsS https://shithub.sh/api/v1/meta | jq '.capabilities | index("gpg-keys")'
    

    Non-null output confirms.

Bulk backfill

  1. Once-off after deploy. Walk every repo's default branch and stamp the verification cache for commits whose signing subkey matches an already-uploaded GPG key. This is what lights up existing signed commits for users whose keys we already had (mostly admins / early testers; the long tail gets covered on next key upload).

    ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd gpg-backfill-all"
    

    The command is idempotent and resumable — re-running picks up where it left off (cache rows are upserted; existing rows short-circuit the walk for that commit). Progress is logged per repo. On a fresh deploy with no pre-existing GPG keys the command is a no-op and exits in a few seconds.

    To limit to a single repo (e.g. for spot-checking after the bulk run):

    ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd \
      gpg-backfill-all --repo=<owner>/<name>"
    

Smoke-test

  1. Log in as a test account and exercise the user-visible flow:

    • Navigate to /settings/keys. Confirm the page renders with the combined SSH + GPG sections.
    • Upload a test GPG key whose UID email matches a verified email on the test account.
    • Navigate to a repo that has signed commits authored by that account on its default branch. The commit list should show green Verified pills within a few seconds of the upload (the backfill worker picks up the eager dispatch).
    • Open /{owner}/{repo}/commits/{sha} for one of those commits. The header should show the larger Verified badge with a click-popover.
  2. Hit the REST surface with a repo:read PAT:

    curl -fsS -H "Authorization: Bearer $PAT" \
      https://shithub.sh/api/v1/repos/<owner>/<name>/commits | \
      jq '.[0].verification'
    

    Expect {verified, reason, signature, payload, verified_at} on every entry.

Rollback

The migrations are additive; rollback is migrate down 3 to reverse them. Re-running with a server build that includes 0066–0068 will re-apply on the next deploy with no data loss (the tables get rebuilt empty; the next eager dispatch repopulates).

If a bad server build forces a rollback to a pre-S51 binary:

ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate down 3"

This drops the three new tables. Any verification cache rows are lost; the bulk backfill on the subsequent re-deploy regenerates them.

See also

View source
1 # Deploy: GPG keys + commit signature verification (S51)
2
3 S51 ships the GPG-keys storage + the verification orchestrator
4 + the Verified-badge rendering + a bulk-backfill admin command,
5 all in one feature-branch merge to trunk. The migrations are
6 additive and the rendering paths fall back to "unsigned"
7 (no badge) on cache miss, so the rollout is safe to do
8 in-band — no maintenance window required.
9
10 ## Pre-deploy
11
12 1. Note the currently-deployed `ldd /opt/shithub/bin/shithubd`
13 output. shithub uses pure-Go OpenPGP via
14 `github.com/ProtonMail/go-crypto`; no new dynamic deps are
15 expected. Diffing post-deploy confirms.
16
17 ```sh
18 ssh root@shithub.sh "ldd /opt/shithub/bin/shithubd" > /tmp/ldd-pre.txt
19 ```
20
21 2. Capture migration status as a baseline:
22
23 ```sh
24 ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate status" \
25 > /tmp/migrate-pre.txt
26 ```
27
28 ## Deploy
29
30 3. Apply migrations. Three new versions land:
31 - `0068_user_gpg_keys.sql` — primary keys table
32 - `0069_user_gpg_subkeys.sql` — subkey fingerprint reverse-lookup
33 - `0070_commit_verification_cache.sql` — verification result cache
34
35 ```sh
36 ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate up"
37 ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate status"
38 ```
39
40 `migrate status` should report all three at version applied.
41
42 4. Quick sanity-check the three new tables exist and are empty:
43
44 ```sh
45 ssh root@shithub.sh "sudo -u shithub psql -d shithub -c '
46 SELECT count(*) FROM user_gpg_keys;
47 SELECT count(*) FROM user_gpg_subkeys;
48 SELECT count(*) FROM commit_verification_cache;'"
49 ```
50
51 Expect `0 / 0 / 0`.
52
53 5. Rolling-restart shithubd. The deploy unit drops one replica
54 at a time; the health endpoint reports 200 once a replica
55 has finished its startup migration check.
56
57 ```sh
58 ssh root@shithub.sh "sudo systemctl restart shithubd@*"
59 ```
60
61 6. Confirm the `gpg-keys` capability landed:
62
63 ```sh
64 curl -fsS https://shithub.sh/api/v1/meta | jq '.capabilities | index("gpg-keys")'
65 ```
66
67 Non-null output confirms.
68
69 ## Bulk backfill
70
71 7. **Once-off after deploy.** Walk every repo's default branch
72 and stamp the verification cache for commits whose signing
73 subkey matches an already-uploaded GPG key. This is what
74 lights up existing signed commits for users whose keys we
75 already had (mostly admins / early testers; the long tail
76 gets covered on next key upload).
77
78 ```sh
79 ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd gpg-backfill-all"
80 ```
81
82 The command is idempotent and resumable — re-running picks
83 up where it left off (cache rows are upserted; existing rows
84 short-circuit the walk for that commit). Progress is logged
85 per repo. On a fresh deploy with no pre-existing GPG keys
86 the command is a no-op and exits in a few seconds.
87
88 To limit to a single repo (e.g. for spot-checking after the
89 bulk run):
90
91 ```sh
92 ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd \
93 gpg-backfill-all --repo=<owner>/<name>"
94 ```
95
96 ## Smoke-test
97
98 8. Log in as a test account and exercise the user-visible flow:
99
100 - Navigate to `/settings/keys`. Confirm the page renders with
101 the combined SSH + GPG sections.
102 - Upload a test GPG key whose UID email matches a verified
103 email on the test account.
104 - Navigate to a repo that has signed commits authored by
105 that account on its default branch. The commit list should
106 show green **Verified** pills within a few seconds of the
107 upload (the backfill worker picks up the eager dispatch).
108 - Open `/{owner}/{repo}/commits/{sha}` for one of those
109 commits. The header should show the larger Verified badge
110 with a click-popover.
111
112 9. Hit the REST surface with a `repo:read` PAT:
113
114 ```sh
115 curl -fsS -H "Authorization: Bearer $PAT" \
116 https://shithub.sh/api/v1/repos/<owner>/<name>/commits | \
117 jq '.[0].verification'
118 ```
119
120 Expect `{verified, reason, signature, payload, verified_at}`
121 on every entry.
122
123 ## Rollback
124
125 The migrations are additive; rollback is `migrate down 3` to
126 reverse them. Re-running with a server build that includes
127 0066–0068 will re-apply on the next deploy with no data loss
128 (the tables get rebuilt empty; the next eager dispatch repopulates).
129
130 If a bad server build forces a rollback to a pre-S51 binary:
131
132 ```sh
133 ssh root@shithub.sh "sudo -u shithub /opt/shithub/bin/shithubd migrate down 3"
134 ```
135
136 This drops the three new tables. Any verification cache rows
137 are lost; the bulk backfill on the subsequent re-deploy
138 regenerates them.
139
140 ## See also
141
142 - User docs: [GPG keys & commit signing](/docs/public/user/gpg-keys.md)
143 - API reference: [GPG keys](/docs/public/api/gpg-keys.md),
144 [Signature verification on commits](/docs/public/api/commits.md#signature-verification)