Skip to content

feat: report the scope GitHub granted and accept owner/repo in --repos - #90

Merged
jferrl merged 1 commit into
mainfrom
feat/token-scope-and-owner-repos
Oct 30, 2026
Merged

jferrl merged 1 commit into
mainfrom
feat/token-scope-and-owner-repos

Conversation

@jferrl

@jferrl jferrl commented Oct 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

When githubauth mints an installation token, GitHub's reply says what the token can actually do: its permissions and, for a scoped token, its repositories. The library threw that away, so a script or agent could not check it got the scope it asked for. It can differ from the request: GitHub adds metadata:read to every token. The token now carries that answer, and githubauth token --json prints it. Separately, --repos acme/api now finds the installation the way --owner acme does.

What this does

Invocation Before After
token --json token, expires_at Also permissions and, for a scoped token, repositories
token --repos acme/api Exit 2: split owner and repo Looks up acme's installation, scopes to api
token --repos acme/api,other/web Exit 2 Exit 2: a token covers one installation
token --repos acme/api --installation 9 Exit 2 Exit 2: the prefix already finds the installation

Changes

  • An installation token's Extra(githubauth.ExtraPermissions) is a map[string]string, and Extra(githubauth.ExtraRepositories) a []string.
  • InstallationPermissions decodes a permission with no field into Other. Field names come from the struct's JSON tags, matched ignoring case as encoding/json does.
  • --repos takes owner/repo, stripped before the names reach GitHub.

Rationale

The scope travels in oauth2.Token's Extra, the standard place for provider data, rather than a new type or method. One consequence: comparing two installation tokens with == panics when GitHub sent a scope, as it already does for any oauth2 token whose Extra holds a map.

An adversarial Codex review found that decoding decided which names had a field from their values, so {"contents":""}, {"Contents":"read"} and a second decode all misbehaved. Matching on the struct's tags fixed all three, and each has a regression test.

Migration Notes

None. Tested against a real App: --repos gopherguru/test --permissions pull_requests:read --json reported {"metadata":"read","pull_requests":"read"} and ["test"].

An installation token now carries GitHub's answer in its oauth2 Extra
fields: ExtraPermissions, a map of the permissions granted, and
ExtraRepositories, the repository names when the token is limited to
some. That can differ from what was asked: metadata:read comes with
every token. githubauth token --json prints both, so a caller can check
the scope it got rather than assume it.

InstallationPermissions now decodes a permission with no field into
Other. Which names have a field is read from the struct's JSON tags,
ignoring case as encoding/json does, so an empty level or a name in
another case stays on its field, and a second decode replaces a level
in Other as it does for a field.

--repos acme/api finds the installation as --owner acme does, the form
actions/create-github-app-token takes. Names of two owners, or an owner
prefix beside --installation or a different --owner, exit 2.

Comparing two installation tokens with == now panics when GitHub sent a
scope, as it does for any oauth2 token whose Extra holds a map.
@codecov

codecov Bot commented Oct 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.86%. Comparing base (de61cf4) to head (a066509).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #90      +/-   ##
==========================================
+ Coverage   97.71%   97.86%   +0.15%     
==========================================
  Files           8        8              
  Lines         787      845      +58     
==========================================
+ Hits          769      827      +58     
  Misses         18       18              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jferrl
jferrl merged commit e17b6f8 into main Oct 30, 2026
10 checks passed
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