nhi: add GitHub Apps syncer (APP_REGISTRATION)#171
Conversation
Connector PR Review: nhi: add GitHub Apps syncer (APP_REGISTRATION)Blocking Issues: 0 | Suggestions: 0 | Threads Resolved: 0 Review SummaryThis PR adds a new read-only Security IssuesNone found. Correctness IssuesNone found. SuggestionsNone. |
7b56ce2 to
4ec249d
Compare
GitHub Apps and their installations were never synced — the connector
authenticates as a GitHub App (mints the App JWT, finds the org
installation) but discarded that identity. Add a read-only `app` resource
type that enumerates org-installed GitHub Apps via
`GET /orgs/{org}/installations` (Organizations.ListInstallations) and emits
each as a non-human identity:
WithNHIType(NHI_TYPE_APP_REGISTRATION, "github.app")
Each app carries TRAIT_APP plus a profile (app_id, app_slug,
installation_id, account_login, target_type, repository_selection). The
endpoint requires Organization administration (read); when the configured
credentials lack it (e.g. a GitHub App installation token), the syncer logs
a warning and skips that org rather than failing the whole sync.
Bumps baton-sdk v0.10.0 -> v0.11.0 for WithNHIType and re-vendors.
Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
…archived (v0.4.5) and can't resolve NonHumanIdentityTrait Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
75ee386 to
e1332c3
Compare
- Remove V1Identifier from app resource (new resource type, no v1 history) - Remove manual 403/404 skip; capability permissions handle access gating - Add CapabilityPermissions annotation (organization_administration:read) to resourceTypeApp - Extract nextPageToken() helper combining parseResp + bag.NextToken; apply to app, api_token, org, team, repository builders — also fixes latent double-extractRateLimitData bug in those builders - Update README and connector.mdx: add GitHub Apps (NHI) to data model, capabilities table, and fine-grained token permissions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| if err != nil { | ||
| return nil, nil, wrapGitHubError(err, resp, "github-connector: failed to list organization app installations") |
There was a problem hiding this comment.
🟡 Suggestion: The previous version of this code gracefully degraded on 403/404 by logging a warning and skipping the org, which was important for GitHub App auth where the installation token may lack organization_administration:read. The CapabilityPermissions annotation on the resource type is used for metadata reporting only (SDK connectorbuilder reads it in GetCapabilities), not for runtime error handling — so a missing permission will now propagate as a PermissionDenied gRPC error and fail the entire sync. If the intent is to make this permission strictly required, this is fine, but it's a behavior change for App-auth users whose installation token doesn't include Administration read access.
There was a problem hiding this comment.
make permission required. if the customer doesn't want to sync apps should disable the resource
1cd59f8 to
ea15782
Compare
Summary
GitHub Apps and their installations are not synced today. The connector authenticates as a GitHub App — it mints the App JWT (
connector.go:getJWTToken), finds the org installation (connector.go:findInstallation), and mints an installation token — but throws that identity away: the resource syncers are org/team/repository/user/invitation/api-key/org_role/enterprise_role only (connector.go ResourceSyncers).This PR adds a new read-only
appresource type that enumerates org-installed GitHub Apps and emits each as a non-human identity (NHI) app registration.This is the Class-B (new-syncer) GitHub item from NHI Phase-1 (RFC §5.8.8, coverage matrix §6 row 6). It follows the proven new-syncer pattern (new resource type + builder + paginated read-only
List+ register + emit), mirroring the existingapi-keysecret syncer (api_token.go).What it does
app(TRAIT_APP,SkipEntitlementsAndGrants), child oforg.Organizations.ListInstallations→GET /orgs/{org}/installations, paginated, per org. This is the org-wide-enumerable window onto GitHub Apps and works with the connector's existingclient(installation-token in App-auth mode, PAT in PAT mode).app_id,app_slug,installation_id,account_login,target_type,repository_selection.Enumerability / auth scope-guard
GET /orgs/{org}/installationsrequires Organization administration (read).connector.go Validate), so this is generally available.Apps vs app definitions: Org-wide, what is enumerable is installations — each installation row carries the app's identity (
app_id,app_slug), which is what we surface as the app registration. There is no PAT-accessible endpoint to list app definitions org-wide (GET /appreturns only the single authenticated app, JWT-only), so we sync the installation view and capture the app identity from it. Within an org a given app has exactly one installation, so this enumerates the distinct installed apps.SDK bump
Bumps
baton-sdkv0.10.0 → v0.11.0 (forWithNHIType/NonHumanIdentityTrait). Repo vendors deps, sogo mod tidy && go mod vendorwas run; vendor changes are scoped tobaton-sdk+modules.txt.Testing
go build ./...✅go vet ./pkg/connector/...✅go test ./...✅ (newTestAppResourceasserts the NHI annotation, app trait, and profile)golangci-lint run ./...→ 0 issues ✅Files
pkg/connector/app.go(new) — resource builder + paginatedList+AppBuilderpkg/connector/app_test.go(new)pkg/connector/connector.go—resourceTypeApp+ registerAppBuilderpkg/connector/org.go—appchild-resource-type annotationgo.mod/go.sum/vendor/— SDK bump