Created
February 8, 2026 22:27
-
-
Save ghabs/96b56ae390d4049b2f58c00be8df789b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Human Approval Workflow: Touch ID Signing for Git | |
| A setup guide for using macOS Touch ID (via Secretive) to cryptographically sign Git commits, creating a verifiable "human approved" checkpoint for AI-assisted development. | |
| ## Overview | |
| This workflow lets AI agents commit freely to feature branches (unsigned), while requiring your physical Touch ID verification to merge to main (signed). GitHub displays a "Verified" badge on signed commits. | |
| ## Prerequisites | |
| - macOS with Touch ID (or a Mac with a YubiKey) | |
| - [Secretive](https://github.com/maxgoedjen/secretive) installed (`brew install --cask secretive`) | |
| - Git installed | |
| - GitHub account | |
| --- | |
| ## Step 1: Create Your Signing Key in Secretive | |
| 1. Open Secretive | |
| 2. Click `+` to create a new key | |
| 3. **Store:** Select "Secure Enclave" (this enforces Touch ID) | |
| 4. **Name:** Something memorable (e.g., `carbon-verified`) | |
| 5. Enable "Require Authentication" | |
| The key is now stored in your Mac's Secure Enclave—it can never be extracted. | |
| --- | |
| ## Step 2: Configure SSH to Use Secretive | |
| Add to `~/.ssh/config`: | |
| ```bash | |
| # Use Secretive's agent for all SSH operations | |
| Host * | |
| IdentityAgent ~/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh | |
| ``` | |
| Verify it works: | |
| ```bash | |
| ssh-add -L | |
| # Should display your Secretive key | |
| ``` | |
| --- | |
| ## Step 3: Add Your Public Key to GitHub | |
| 1. In Secretive, click your key → "Copy Public Key" | |
| 2. Go to GitHub → Settings → SSH and GPG Keys | |
| 3. Click "New SSH Key" | |
| 4. **Key type:** Select "Signing Key" (important!) | |
| 5. **Title:** Same as your key name (e.g., `carbon-verified`) | |
| 6. Paste your public key and save | |
| --- | |
| ## Step 4: Configure Git for SSH Signing | |
| ```bash | |
| # Use SSH signing (not GPG) | |
| git config --global gpg.format ssh | |
| # Set your signing key (paste your public key, or path to it) | |
| # Option A: Direct public key | |
| git config --global user.signingkey "ssh-ed25519 AAAA... your-key-name" | |
| # Option B: Path to public key file (Secretive provides this) | |
| git config --global user.signingkey "/Users/YOUR_USERNAME/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/PublicKeys/YOUR_KEY_ID.pub" | |
| # IMPORTANT: Don't auto-sign commits | |
| # This lets AI agents commit unsigned; you sign manually | |
| git config --global commit.gpgsign false | |
| # Optional: Set up local signature verification | |
| git config --global gpg.ssh.allowedSignersFile ~/.git-allowed-signers | |
| # Create the allowed signers file (for local verification) | |
| echo "your@email.com $(cat /path/to/your/public/key.pub)" >> ~/.git-allowed-signers | |
| ``` | |
| --- | |
| ## Step 5: Set Up GitHub Branch Protection | |
| For each repository you want to protect: | |
| 1. Go to repo → Settings → Branches | |
| 2. Click "Add branch protection rule" | |
| 3. Branch name pattern: `main` | |
| 4. Enable: | |
| - ☑️ **Require signed commits** | |
| - ☑️ **Do not allow bypassing the above settings** | |
| 5. Optional but stricter: | |
| - ☑️ Require a pull request before merging | |
| 6. Save | |
| --- | |
| ## Step 6: Test Your Setup | |
| ```bash | |
| # Create a test repo (or use existing) | |
| mkdir test-signing && cd test-signing | |
| git init | |
| # Make an unsigned commit (simulating AI agent work) | |
| echo "AI wrote this" > file.txt | |
| git add file.txt | |
| git commit -m "Agent work: initial file" | |
| # No Touch ID prompt - this is unsigned | |
| # Make a signed commit (your approval) | |
| git commit --allow-empty -S -m "Human approved: initial work" | |
| # Touch ID prompt should appear! | |
| # Verify signatures | |
| git log --show-signature -2 | |
| ``` | |
| You should see: | |
| - First commit: No signature | |
| - Second commit: "Good signature from..." | |
| --- | |
| ## The Workflow in Practice | |
| ```bash | |
| # AI agent works on a feature branch | |
| git checkout -b feature/new-thing | |
| # ... AI makes commits ... | |
| git push origin feature/new-thing # ✅ Allowed (no protection on feature branches) | |
| # You review and approve with signed merge | |
| git checkout main | |
| git pull origin main | |
| git merge --no-ff -S feature/new-thing -m "Human approved: new feature" | |
| # → Touch ID prompt | |
| git push origin main # ✅ Allowed (signed) | |
| ``` | |
| The `-S` flag triggers signing, which requires Touch ID. | |
| --- | |
| ## Quick Reference | |
| | Command | What it does | | |
| |---------|--------------| | |
| | `git commit -m "msg"` | Unsigned commit (AI work) | | |
| | `git commit -S -m "msg"` | Signed commit (human approval, Touch ID required) | | |
| | `git merge --no-ff -S branch` | Signed merge commit | | |
| | `git log --show-signature` | View signature status | | |
| | `git verify-commit HEAD` | Verify latest commit signature | | |
| --- | |
| ## Troubleshooting | |
| **Touch ID not prompting:** | |
| - Check Secretive is running | |
| - Verify `ssh-add -L` shows your key | |
| - Ensure `IdentityAgent` path is correct in `~/.ssh/config` | |
| **GitHub shows "Unverified":** | |
| - Confirm your Git email matches a verified email on GitHub: `git config user.email` | |
| - Ensure you added the key as a "Signing Key" (not just authentication) | |
| **"error: Load key failed":** | |
| - The key path in `user.signingkey` may be wrong | |
| - Try using the full public key string instead of the path |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment