Skip to content

chore: add pre-merge identity guard - #20

Open
Sentinel-Bluebuilder wants to merge 2 commits into
masterfrom
chore/merge-identity-guard
Open

chore: add pre-merge identity guard#20
Sentinel-Bluebuilder wants to merge 2 commits into
masterfrom
chore/merge-identity-guard

Conversation

@Sentinel-Bluebuilder

Copy link
Copy Markdown
Owner

Why

The merge commit for PR #19 (8f5b0f2) landed on master authored with a personal email, even though every one of the five commits inside that PR was correctly authored as the bot.

This was not a wrong-account mistake. GitHub's own record shows merged_by: Sentinel-Bluebuilder — the correct bot account performed the merge. The actual cause:

  1. gh pr merge builds the merge commit server-side. Local user.email is ignored, and no client-side git hook can intercept it, because no local commit ever happens.
  2. GitHub stamps that commit with the merging account's primary email.
  3. The bot account did not have "Keep my email addresses private" enabled, so its primary email was a personal address.

The real fix is a GitHub setting, not this script

Signed in as the bot → Settings → Emails → "Keep my email addresses private"https://github.com/settings/emails

There is no API for it. PATCH user/email/visibility returns visibility: private but only controls public profile display — it does not change what server-side merge commits are stamped with. Verified during this work.

This affects every repo the bot merges, not just this one.

What this script adds

Enforcement for that setting:

node scripts/check-merge-identity.mjs && gh pr merge <N> --merge

The && is what makes it load-bearing rather than advisory.

One implementation note worth reading

It reads gh api user/emails (the true primary), not gh api user.email. The latter is the public profile email and is null whenever unset — which reads as "safe" while the primary is still personal.

My first version used that field and gave a false PASS on the exact account that caused the leak. It now fails closed when it cannot read the deciding value (e.g. a token missing the user scope) rather than guessing.

Verified: blocks on the bot account while its primary email is personal, and blocks on a scope-less token.

⚠️ Do not merge this with the button yet

Merging before the GitHub setting is enabled would stamp another personal email onto a new merge commit — reproducing the bug this PR exists to prevent. Enable the setting first, run the guard, then merge.

https://claude.ai/code/session_01LQj6ekufSijMXPcXUD3596

Sentinel-Bluebuilder and others added 2 commits August 10, 2026 06:54
…-failover

Merging the RPC self-healing failover work. Tested against mainnet with real money: 4/4 funded writes landed with the live endpoint benched each time, all 33 changed routes driven live (52/52), full regression suite green.

Keplr/Privy client-signed paths remain untested — see the PR body.
The merge commit for PR #19 (`8f5b0f2`) landed on master authored as a
personal email, even though every commit inside the PR was correctly authored
as the bot.

This was NOT a wrong-account mistake. GitHub's record for PR #19 shows
`merged_by: Sentinel-Bluebuilder` — the correct bot account performed the
merge. The actual cause:

  1. `gh pr merge` builds the merge commit SERVER-SIDE. Local git config is
     ignored, and no client-side hook can intercept it because no local commit
     ever happens.
  2. GitHub stamps that commit with the merging account's PRIMARY email.
  3. The bot account did not have "Keep my email addresses private" enabled,
     so its primary email was a personal address.

The real fix is that GitHub setting (browser-only — there is no API for it;
`PATCH user/email/visibility` only controls PUBLIC PROFILE display and does
NOT change what server-side commits are stamped with).

This script is the enforcement check for it:

  node scripts/check-merge-identity.mjs && gh pr merge <N> --merge

Note it reads `gh api user/emails` (the real primary), NOT `gh api user`.email
— the latter is the PUBLIC profile email and is null whenever the profile
email is unset, which reads as "safe" while the primary is still personal.
A first version of this script used that field and gave a false PASS on the
exact account that caused the leak; it now fails closed when it cannot read
the deciding value, rather than guessing.

Verified: blocks on the bot account (primary email personal), and blocks on a
token lacking the `user` scope rather than reporting safe.

Claude-Session: https://claude.ai/code/session_01LQj6ekufSijMXPcXUD3596
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant