fix: github-account hook converges the active account instead of blocking#99
Merged
Conversation
β¦king The guard blocked every gh command on account mismatch β including the gh auth switch it prescribed as the remedy, deadlocking agent sessions. It now runs gh auth switch --hostname github.com --user <configured> itself on mismatch (or when no account is active), re-checks, and passes with a visible warning naming the switch. Blocking remains for the unrecoverable cases: gh missing, status probe failure, or a failed switch β the latter with gh's own stderr and gh auth login guidance. Mismatch is a typed state, not a parsed diagnostic; the read-only release-readiness report keeps its non-mutating wording. Hook timeout doubled for the switch+recheck round-trips; hook docs updated.
This was referenced Jul 7, 2026
External review round 1 found the retargeting hazard: under a mismatch, gh auth logout would first converge the global pointer to the configured account and then log THAT account out, not the one the user targeted β same misdirection class for gh auth switch and refresh. Identity administration is the user's domain: when every gh invocation in the command is an auth subcommand, the hook passes through with no probe and no switch; compounds mixing auth with resource-touching gh usage still converge. Docs sharpen the residual-risk disclosure per the same review: convergence writes the shared pointer on every mismatched call β reads included β raising collision frequency versus the old pure-read check; the window's shape is unchanged, its trigger rate is not.
Owner
Author
External review β round 1 (Codex, off-PR) β findings and dispositionsFresh-thread adversarial review of a fail-closed guard's behavior change; reviewer ran all tests, verified the six behavioral branches, reproduced the original deadlock from the old code, and confirmed the tier layering with PR #100. Verdict: approve, no blockers. Both should-fixes landed in
Reviewer also confirmed: the release-flow partition stays correct (enforcement converges, reporting stays read-only, |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & Why
The
github-accountguard (shipped in v2.0.0-alpha.5) blocked everyghcommand on account mismatch β including thegh auth switchcommand its own error message prescribed as the remedy. In agent sessions, where hooks intercept allghinvocations, that's a deadlock: the state being checked can only be changed by the command class being blocked. Hit live on 2026-07-07 while opening PR #97.Redesign per direction: the guard's job is to converge the environment on the configured account, not dead-end on it. On mismatch (or authenticated-but-no-active-account) the check now runs
gh auth switch --hostname github.com --user <configured>itself, re-checks that the switch took, and passes with a visible warning naming the mutation β never silently. Blocking remains for the genuinely unrecoverable cases: gh not installed, status probe failure, or a failed switch (typically the account isn't authenticated) β the latter surfacing gh's own stderr plusgh auth loginguidance.Design notes:
classifyGitHubAccount/resolveGitHubAccountwith injected status/switch runners), not a parsed diagnostic string.Review focus
check_test.go: match β no switch attempted; no-config β no gh execution; mismatch β switch β pass-with-warning (asserts switch args and the re-check); switch-fails β block with login guidance; gh missing / probe failure β block unchanged.switched active gh account to "<expected>" (was "<actual>") for this projectβ this mutation is global gh state, so visibility is the safety mechanism.GH_TOKENresolved per command), which is skill-guidance territory, not enforceable by a check hook β tracked for the hooks re-evaluation.Verification
Migration / breaking changes
Behavior change to the guard:
ghcommands under a mismatched account now proceed after an automatic switch (with warning) instead of failing. Projects relying on the hard block as an identity firewall should note the block now only fires when convergence is impossible.