Skip to content

Set up commit and tag signing (SSH) and decide on key-backup strategy #8

Description

@tino1b2be

Context

GIT_SIGN_COMMITS=true is set globally on the developer machine but no signing key (GPG or SSH) is configured. Every commit and tag operation emits a "signing failed" warning, and the operation silently falls back to unsigned. v2.0.0 and v2.1.0 are both unsigned annotated tags as a result — consistent with each other, but no "Verified" badge on GitHub.

git cat-file tag v2.0.0 and v2.1.0 both show no BEGIN PGP SIGNATURE block. GitHub shows zero GPG and zero SSH signing keys on the account as of v2.1.0.

Desired state

Every release tag (and ideally every commit on master) carries a cryptographic signature that:

  • Shows as "Verified" on the GitHub web UI and in commit/tag hover cards.
  • Binds each release to a single known-good developer identity.
  • Has a documented backup/recovery story for the private key material.

Recommended approach

SSH signing, reusing an Ed25519 SSH key. Reasons:

  • No separate GPG toolchain to maintain; ssh-keygen -Y sign is used internally by modern git.
  • Same key can serve both push authentication and signing (two GitHub settings slots; one local file).
  • pinentry-mac / gpg-agent setup not required.
  • Matches mainstream Mac-developer practice as of 2025+.

Action items

  • Generate an Ed25519 SSH signing key on the dev Mac (ssh-keygen -t ed25519). Decide on passphrase vs. empty.
  • Upload the public key to GitHub twice: once as an authentication key (admin:public_key), once as a signing key (admin:ssh_signing_key), or as both via the web UI's dual-purpose checkbox.
  • Configure git globally:
    git config --global gpg.format ssh
    git config --global user.signingkey ~/.ssh/id_ed25519.pub
    git config --global commit.gpgsign true
    git config --global tag.gpgSign true
    
  • Pick a backup strategy for the private key with at least two independent failure modes (options: 1Password/Bitwarden secure note + AWS SSM SecureString, or iCloud Keychain password sync + SSM, or similar).
  • Document the laptop-migration flow in CONTRIBUTING.md or a new docs/release-process.md so the next Me knows where the key lives and how to restore it.
  • Remove or rationalise the global GIT_SIGN_COMMITS=true config so that either (a) it's enforced and actually working, or (b) it's unset and not spamming every commit with signing-failed warnings.
  • From v2.2.0 onward: cut every release tag signed (git tag -s), bake a "signing required" check into the release checklist.

Open questions

  • Do we want historical tags (v2.0.0, v2.1.0) re-signed retroactively? Git allows deleting and re-creating a signed tag pointing at the same commit, but it's destructive to anyone who's already pulled the old tag. Probably leave them unsigned and document the transition.
  • Is Maven Central publishing on the roadmap? If yes, we'd also need GPG for artifact signing (separate from commit/tag signing). Keep the two concerns decoupled even if we eventually have both.

References

Not in scope for this issue

  • Maven Central publishing itself (separate future spec; see product.md out-of-scope list).
  • Migration of the legacy com.tino1b2be.dtmfdecoder namespace (already declared removed, no shim planned).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions