Never sign byre's own commits on the server

This commit is contained in:
Ian Gulliver
2026-10-21 14:24:34 -07:00
parent a7cfd91399
commit 35683e1114
4 changed files with 9 additions and 14 deletions
-9
View File
@@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strings" "strings"
) )
@@ -13,20 +12,12 @@ func signingCmd(args []string) {
usage() usage()
} }
checkout := args[0] checkout := args[0]
common := gitOut(checkout, "rev-parse", "--path-format=absolute", "--git-common-dir")
if gitOut(checkout, "rev-parse", "--path-format=absolute", "--git-dir") != common {
fatal("checkout is a linked worktree; run byre signing on its main checkout", "checkout", checkout)
}
unsigned := filepath.Join(common, "unsigned.gitconfig")
gitOut(checkout, "config", "commit.gpgsign", "true") gitOut(checkout, "config", "commit.gpgsign", "true")
gitOut(checkout, "config", "--file", unsigned, "commit.gpgsign", "false")
gitOut(checkout, "config", "includeIf.gitdir:"+filepath.Join(common, "worktrees")+"/**.path", "unsigned.gitconfig")
signing := gitOut(checkout, "config", "--type=bool", "--get", "commit.gpgsign") signing := gitOut(checkout, "config", "--type=bool", "--get", "commit.gpgsign")
if signing != "true" { if signing != "true" {
fatal("checkout's commit.gpgsign is not true after setting it", "checkout", checkout, "value", signing) fatal("checkout's commit.gpgsign is not true after setting it", "checkout", checkout, "value", signing)
} }
fmt.Printf("%s: commit.gpgsign %s\n", checkout, signing) fmt.Printf("%s: commit.gpgsign %s\n", checkout, signing)
fmt.Printf("%s/worktrees/*: commit.gpgsign %s\n", common, gitOut(checkout, "config", "--file", unsigned, "--type=bool", "--get", "commit.gpgsign"))
} }
func gitOut(dir string, args ...string) string { func gitOut(dir string, args ...string) string {
+2 -2
View File
@@ -97,9 +97,9 @@ Coordination of merges, discards, reviews, ready-for-merge prompts, workflow sta
## Signing merges ## Signing merges
byre never signs with a key on the machine it runs on. When a project checkout's `commit.gpgsign` is true (`git -C <checkout> config --type=bool --get commit.gpgsign` prints it), the squash commit of a merge is signed on the merging user's most recently active Mac, so a key that never leaves that Mac's Secure Enclave and needs a fingerprint works. The Mac runs its own git signing config, as git does: `gpg.format` (`openpgp` or `x509`; `ssh` is not supported), the program when it isn't `gpg`/`gpgsm`, and `user.signingkey` when the program can't find the key from the user's byre git identity (not the Mac's `user.email`). The program must print `[GNUPG:] SIG_CREATED ` on its status fd, as git requires. A Touch ID prompt left unanswered for 2 minutes fails the merge. The notes commit is not signed. byre never signs with a key on the machine it runs on: every git command it runs there, except `git config`, gets `-c commit.gpgsign=false`, so its end-of-turn, snapshot and merge-in commits stay unsigned whatever the server's config says. A signing program left to run under the launchd service can wait forever on a prompt nobody sees (`ac-sign` waiting on AppleConnect did), and the turn would never end. Those commits never reach the default branch anyway; the squash replaces them. When a project checkout's `commit.gpgsign` is true (`git -C <checkout> config --type=bool --get commit.gpgsign` prints it), the squash commit of a merge is signed on the merging user's most recently active Mac, so a key that never leaves that Mac's Secure Enclave and needs a fingerprint works. The Mac runs its own git signing config, as git does: `gpg.format` (`openpgp` or `x509`; `ssh` is not supported), the program when it isn't `gpg`/`gpgsm`, and `user.signingkey` when the program can't find the key from the user's byre git identity (not the Mac's `user.email`). The program must print `[GNUPG:] SIG_CREATED ` on its status fd, as git requires. A Touch ID prompt left unanswered for 2 minutes fails the merge. The notes commit is not signed.
`byre signing <checkout>` turns it on for a project; agents learn it from the `signing` knowledge-base article. It sets `commit.gpgsign` true in the checkout and false for its task worktrees, which share that config and would otherwise try to sign end-of-turn commits on the server, and fail. `extensions.worktreeConfig` wouldn't do it, since `git worktree add` copies the checkout's `config.worktree` into each new worktree, nor would the server's global config, which is read before the checkout's. It refuses a checkout that is itself a linked worktree, since the task-worktree exception would turn signing off for it too. No restart is needed; `git -C <checkout> cat-file commit HEAD` shows the `gpgsig` header. `byre signing <checkout>` turns it on for a project; agents learn it from the `signing` knowledge-base article. It sets `commit.gpgsign` true in the checkout; a global `commit.gpgsign` true on the server does the same for every project. Agents' own `git commit` in a task worktree reads that config and runs the signing program on the server. No restart is needed; `git -C <checkout> cat-file commit HEAD` shows the `gpgsig` header.
## Client Macs ## Client Macs
+2 -2
View File
@@ -2,7 +2,7 @@ How byre signs merge commits on the merging user's Mac, and how to turn it on fo
# Signing merge commits # Signing merge commits
byre never signs with a key on the machine it runs on. When a project checkout has `commit.gpgsign` true, the squash commit of a Merge or `merge_to_main` is signed on the merging user's most recently active connected Mac, so a key that never leaves that Mac (a Secure Enclave key behind Touch ID, say) works. The merge fails when that user has no app connected. byre never signs with a key on the machine it runs on: its own end-of-turn and snapshot commits there are always unsigned. When a project checkout (or the server's global config) has `commit.gpgsign` true, the squash commit of a Merge or `merge_to_main` is signed on the merging user's most recently active connected Mac, so a key that never leaves that Mac (a Secure Enclave key behind Touch ID, say) works. The merge fails when that user has no app connected.
## Turning it on ## Turning it on
@@ -12,7 +12,7 @@ Run, on the machine byre runs on:
byre signing <checkout> byre signing <checkout>
``` ```
`<checkout>` is the project's main checkout, not a task worktree. It sets `commit.gpgsign` true for the checkout and false for its task worktrees (which would otherwise try to sign on the server and fail), prints both values, and fails unless the checkout's reads true. It refuses a checkout that is itself a linked worktree. No restart is needed; the next merge reads the config. `<checkout>` is the project's main checkout. It sets `commit.gpgsign` true for the checkout, prints it, and fails unless it reads true. No restart is needed; the next merge reads the config.
## What the Mac needs ## What the Mac needs
+5 -1
View File
@@ -384,7 +384,11 @@ func runNetwork(ctx context.Context, dir string, args ...string) (string, string
} }
func runCodeInput(ctx context.Context, dir string, env []string, stdin io.Reader, args ...string) (string, string, int, error) { func runCodeInput(ctx context.Context, dir string, env []string, stdin io.Reader, args ...string) (string, string, int, error) {
cmd := procgroup.CommandContext(ctx, "git", args...) argv := args
if args[0] != "config" {
argv = append([]string{"-c", "commit.gpgsign=false"}, args...)
}
cmd := procgroup.CommandContext(ctx, "git", argv...)
cmd.Dir = dir cmd.Dir = dir
cmd.Env = append(os.Environ(), env...) cmd.Env = append(os.Environ(), env...)
cmd.Stdin = stdin cmd.Stdin = stdin