Problem
Integrity filtering currently determines a user's trust level based on the author_association field from GitHub API responses. This field is unreliable for org admins who haven't been explicitly added as collaborators on a specific repository.
How it works today
The Rust guard maps author_association to integrity levels in helpers.rs:960-980:
| author_association |
Integrity Level |
| OWNER, MEMBER, COLLABORATOR |
approved (writer) |
| CONTRIBUTOR, FIRST_TIME_CONTRIBUTOR |
unapproved (reader) |
| FIRST_TIMER, NONE |
none |
The bug
GitHub's author_association field reflects the user's direct relationship with the repository, not their effective permissions. An org admin who:
- Has full admin access to a repo via org ownership
- But hasn't been explicitly added as a collaborator
...gets author_association: "CONTRIBUTOR" (if they've contributed before) or "NONE" (if they haven't). This maps to unapproved or none integrity, causing their issues, PRs, and comments to be filtered out by the integrity filter.
This is a fundamental limitation of the GitHub API's author_association field — it doesn't know about org-level permissions.
Impact
- Org admins' content is silently filtered from agentic workflow results
- Users must work around this by explicitly adding themselves as collaborators, using
min-integrity: none, or configuring trusted-users
- The workarounds defeat the purpose of integrity filtering or require per-user configuration
Upstream issue
See github/gh-aw#23565
Proposed Solution
Supplement author_association with a call to the collaborator permission endpoint:
GET /repos/{owner}/{repo}/collaborators/{username}/permission
This endpoint returns the user's effective permission level, which correctly includes inherited org permissions:
{
"permission": "admin",
"user": {
"login": "example-user",
"id": 12345
}
}
Permission-to-integrity mapping
| Collaborator Permission |
Integrity Level |
| admin, maintain, write |
approved (writer) |
| read (triage) |
unapproved (reader) |
| none |
none |
Implementation approach
Option A: Gateway-side enrichment (recommended)
Add a new enrichment call in the gateway proxy (internal/proxy/proxy.go) alongside the existing pull_request_read and issue_read enrichment paths:
- When the Rust guard needs to determine integrity for an issue/PR author, the gateway calls
GET /repos/{owner}/{repo}/collaborators/{username}/permission using the enrichment token
- Pass the
permission field to the guard alongside (or instead of) author_association
- The guard uses
permission as the primary signal, falling back to author_association if the permission call fails (e.g., insufficient token scopes)
This fits naturally into the existing restBackendCaller pattern in proxy.go:274-341.
Option B: Guard-side callback
Extend the WASM guard's backend callback interface to support a new get_collaborator_permission call. The guard would call this from tool_rules.rs when labeling issues/PRs, similar to the existing get_pull_request_facts() and get_issue_author_info() callbacks in backend.rs.
Key considerations
-
Token permissions: The GET /repos/{owner}/{repo}/collaborators/{username}/permission endpoint works with the standard GITHUB_TOKEN in Actions as long as the query is scoped to the same repository (see gh-aw#23565 comment). No additional token scopes needed.
-
Caching: Permission lookups could be cached per (repo, username) pair for the duration of a session to avoid redundant API calls.
-
Fallback: If the permission endpoint returns an error (403, 404), fall back to the existing author_association logic so the feature degrades gracefully.
-
Existing precedent: The gh-aw compiler already uses github.rest.repos.getCollaboratorPermissionLevel() for /slash_command permission checks (see checkRepositoryPermission in gh-aw's check_membership.cjs).
Files that would need changes
internal/proxy/proxy.go — Add enrichment call for collaborator permission
guards/github-guard/rust-guard/src/labels/backend.rs — Add get_collaborator_permission callback and data structure
guards/github-guard/rust-guard/src/labels/helpers.rs — Add collaborator_permission_floor() mapping function
guards/github-guard/rust-guard/src/labels/tool_rules.rs — Use permission-based integrity as primary signal for issues/PRs
Problem
Integrity filtering currently determines a user's trust level based on the
author_associationfield from GitHub API responses. This field is unreliable for org admins who haven't been explicitly added as collaborators on a specific repository.How it works today
The Rust guard maps
author_associationto integrity levels inhelpers.rs:960-980:The bug
GitHub's
author_associationfield reflects the user's direct relationship with the repository, not their effective permissions. An org admin who:...gets
author_association: "CONTRIBUTOR"(if they've contributed before) or"NONE"(if they haven't). This maps tounapprovedornoneintegrity, causing their issues, PRs, and comments to be filtered out by the integrity filter.This is a fundamental limitation of the GitHub API's
author_associationfield — it doesn't know about org-level permissions.Impact
min-integrity: none, or configuringtrusted-usersUpstream issue
See github/gh-aw#23565
Proposed Solution
Supplement
author_associationwith a call to the collaborator permission endpoint:This endpoint returns the user's effective permission level, which correctly includes inherited org permissions:
{ "permission": "admin", "user": { "login": "example-user", "id": 12345 } }Permission-to-integrity mapping
Implementation approach
Option A: Gateway-side enrichment (recommended)
Add a new enrichment call in the gateway proxy (
internal/proxy/proxy.go) alongside the existingpull_request_readandissue_readenrichment paths:GET /repos/{owner}/{repo}/collaborators/{username}/permissionusing the enrichment tokenpermissionfield to the guard alongside (or instead of)author_associationpermissionas the primary signal, falling back toauthor_associationif the permission call fails (e.g., insufficient token scopes)This fits naturally into the existing
restBackendCallerpattern inproxy.go:274-341.Option B: Guard-side callback
Extend the WASM guard's backend callback interface to support a new
get_collaborator_permissioncall. The guard would call this fromtool_rules.rswhen labeling issues/PRs, similar to the existingget_pull_request_facts()andget_issue_author_info()callbacks inbackend.rs.Key considerations
Token permissions: The
GET /repos/{owner}/{repo}/collaborators/{username}/permissionendpoint works with the standardGITHUB_TOKENin Actions as long as the query is scoped to the same repository (see gh-aw#23565 comment). No additional token scopes needed.Caching: Permission lookups could be cached per
(repo, username)pair for the duration of a session to avoid redundant API calls.Fallback: If the permission endpoint returns an error (403, 404), fall back to the existing
author_associationlogic so the feature degrades gracefully.Existing precedent: The gh-aw compiler already uses
github.rest.repos.getCollaboratorPermissionLevel()for/slash_commandpermission checks (seecheckRepositoryPermissionin gh-aw'scheck_membership.cjs).Files that would need changes
internal/proxy/proxy.go— Add enrichment call for collaborator permissionguards/github-guard/rust-guard/src/labels/backend.rs— Addget_collaborator_permissioncallback and data structureguards/github-guard/rust-guard/src/labels/helpers.rs— Addcollaborator_permission_floor()mapping functionguards/github-guard/rust-guard/src/labels/tool_rules.rs— Use permission-based integrity as primary signal for issues/PRs