Development record
external-review.yml's role_of() folds every 'gh api collaborators/<u>/permission' non-zero exit into the string 'none' via '2>/dev/null || echo none', indistinguishable from a legitimate no-role answer, so a transient/permission failure silently misclassifies authors and drops approvals; the job grants only contents:read + pull-requests:read while that endpoint needs push access (or an App members permission), so it likely 403s for every lookup and wedges the gate red for all human PRs with no diagnostic. Not fixed autonomously: required-check workflow, and the permission behaviour needs a real Actions run to confirm
external-review.yml's role_of() folds every 'gh api collaborators/<u>/permission' non-zero exit into the string 'none' via '2>/dev/null || echo none', indistinguishable from a legitimate no-role answer, so a transient/permission failure silently misclassifies authors and drops approvals; the job grants only contents:read + pull-requests:read while that endpoint needs push access (or an App members permission), so it likely 403s for every lookup and wedges the gate red for all human PRs with no diagnostic. Not fixed autonomously: required-check workflow, and the permission behaviour needs a real Actions run to confirm
Evidence
.github/workflows/external-review.yml—role_of() { gh api "repos/$REPO/collaborators/$1/permission" --jq .role_name 2>/dev/null || echo none; }folds every non-zero exit (403 / 404 / rate-limit / network / jq error) intonone, indistinguishable from a legitimate no-role answer, so a transient/permission failure misclassifies the author as external or drops a real approval.- The job grants
contents: read+pull-requests: readonly; thecollaborators/{u}/permissionendpoint needs push access (or, for an App token, the orgmemberspermission), so it likely 403s for every lookup — silently wedging the gate red for all human-authored PRs with no diagnostic. Landed today (iss-281).
Adversarial review
CONFIRMED (substantive, with a verification caveat) by an independent refuter: the masking is
certain from the code; the "breaks every PR" severity rests on the token genuinely lacking
endpoint access, which needs a real Actions run to confirm. Proposed fix (NOT applied this
round): fail loud on a genuine API error, and either add the endpoint's permission or derive
role from author_association (which the existing token can read). Left open: required-check
workflow, unverifiable here.
Grounds
- pursued: an API error in a role lookup turns the check red with a message naming the lookup, never a misclassified author or a silently dropped approval; shown wrong by an external-review log reporting role none for a login whose permission call failed
Frontmatter
| id | iss-302 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-302-external-review-yml-s-role-of-folds.md
open on GitHub ↗ · commit history ↗
mentions2
- dcn-26081900000000032026-08-19 — bughunt round 1 (branch bughunt-b/round-1): captured iss-291..iss-304 and fixed
- iss-281Externally submitted PRs and issues must be reviewed by at least two invited collaborators (hard rule, maintainer decision 2026-08-19). PR half: enforceable as a required status check counting approvals from collaborators with role triage or above, running on pull_request_target so a fork cannot neuter it. Issues half: GitHub issues carry no native review gate — ledger captures land via PRs and inherit the PR rule; tracker issues rely on intake S1 process until a mechanism exists