feat(bin): ship the agent credential shims + lint ~/.local/bin - #13
Closed
natevick wants to merge 2 commits into
Closed
feat(bin): ship the agent credential shims + lint ~/.local/bin#13natevick wants to merge 2 commits into
natevick wants to merge 2 commits into
Conversation
added 2 commits
August 1, 2026 08:14
Agent accounts now hold one fine-grained PAT per GitHub org under ~/.config/github-pats/<owner>, selected by lowercasing the owner from the remote URL. Scope is enforced server-side, so the tokens are narrow enough to be ambient — a routine fetch or `gh pr view` no longer costs an approval round-trip. Guarded on .agent: on a machine without the helper installed this block would break github.com auth outright, so it must never render on the Mac. Verified both ways with `chezmoi execute-template --override-data`. Two details that are load-bearing and easy to lose: - `helper =` resets the list first. For multi-valued keys git APPENDS, so without the reset the `!gh auth git-credential` helper above still gets consulted first. - useHttpPath=true, or git omits `path=` from the credential request and the helper has no owner to key a token on.
PR #12 added a gitconfig pointing at a credential helper the repo did not contain, so a rebuilt agent host got config with nothing behind it. Ship the three shims it depends on: gh injects the per-org PAT, resolving owner from -R/--repo, GH_REPO, an `gh api` path, a POSITIONAL owner/repo, or the cwd's origin. No default-org fallback: a repo-less call runs unauthenticated rather than quietly carrying an org credential. git refuses force-push and branch-delete, audits, and notifies. An ACCIDENT CATCHER, not a control — anything running as the agent can call /usr/bin/git or set NORM_ALLOW_FORCE=1. It fails OPEN to real git by design; breaking every git call would be worse than missing one force-push. git-credential-github-org one PAT per org, keyed on the remote URL's owner. All three append to ~/.local/state/norm-gh-audit.jsonl (0600, created before first write — the ambient umask would otherwise leave it world-readable). The token value is never logged. Gated in .chezmoiignore on .agent: `gh` and `git` SHADOW the real binaries, so on a host without ~/.config/github-pats they would break github.com auth outright. Verified both renderings with --override-data. Also wire home/dot_local/bin/* into the shellcheck job. Those files shadow real binaries and were outside the linter's reach; all four pass clean (0.11.0).
Owner
Author
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.
Follow-up to #12, which shipped a gitconfig pointing at a credential helper this repo did not contain — so a rebuilt agent host got config with nothing behind it. This adds the three shims.
gh-R/--repo,GH_REPO, angh apipath, a positionalowner/repo, or the cwd origin. No default-org fallback — a repo-less call runs unauthenticated rather than quietly carrying an org credential.gitgit-credential-github-orgThe
gitguard is an accident catcher, not a control. Anything running as the agent can call/usr/bin/git, use the API, or setNORM_ALLOW_FORCE=1(which is itself audited and notified). It exists because the broker's hard-deny on force-push does not reach the ambient PAT path. It fails open to real git by design — breaking every git call would be worse than missing one force-push. Non-pushsubcommands are untouched, soclean -fd/checkout -f/tag -f/branch -dstill work..chezmoiignoreon.agent:ghandgitshadow real binaries, so on a host with no~/.config/github-patsthey would break github.com auth outright. Both renderings verified with--override-data.0600before first write; the ambient umask would otherwise leave it world-readable. The token value is never logged.home/dot_local/bin/*is now covered by the shellcheck job — these shadow real binaries and were outside the linter entirely. All four files pass clean (shellcheck 0.11.0).Verified on the agent host: 51 behavioural tests across the three shims incl. sabotage passes, a real blocked force-push (nothing reached the remote), and a real push+delete cycle on a throwaway branch.