fix: scope maintainer-discover to user installations and bound sweep (#784) - #832
Conversation
…oder-s-OG-s#784) The maintainer-discover sweep ran unbounded O(users x installs x repos) GitHub API calls per cron tick, enabling cross-installation rate limit exhaustion. The function loaded ALL global installations instead of scoping to the user's junction rows, and used force:true which bypassed the dedup cache. Fixes: - Scope discoverForUser installations to user's junction rows via github_installation_users join, eliminating cross-org API calls - Remove force:true from sweep events, respecting the 1-hour dedup cache - Reduce sweep batch from 100 to 20 users per tick - Skip recently-discovered users in sweep instead of force-processing
|
@namann5 is attempting to deploy a commit to the codersogs-3057's projects Team on Vercel. A member of the Team first needs to authorize it. |
jakharmonika364
left a comment
There was a problem hiding this comment.
Callers in process-membership-events.ts should resolve and pass that install's id (org membership -> look up by organization.login; repo collaborator -> the installation_repositories row already looked up at line 71–76) instead of only {userId, githubHandle}.
…tall, update callers
|
@jakharmonika364 resolved -- 1) added installationId to DiscoverEvent type 2) target install fetched and included when installationId is passed (even if not yet in junction table) 3) processMembershipEvent resolves install by org login 4) processMemberEvent passes install_id from installation_repositories row |
…d no installationId (Coder-s-OG-s#832 review)
| const installRows = targetInstall?.data | ||
| ? [...knownInstalls, targetInstall.data].filter(dedupeById) | ||
| : knownInstalls.length > 0 || installationId | ||
| ? knownInstalls | ||
| : (( | ||
| await sb | ||
| .from('github_installations') | ||
| .select('id, account_login, account_type') | ||
| .is('uninstalled_at', null) | ||
| ).data ?? []); |
There was a problem hiding this comment.
This still leaves a gap: src/app/actions/profile.ts's sign-in trigger (void inngest.send({ name: 'maintainer/discover', data: { userId, githubHandle } }), not touched by this PR) never passes installationId - it can't, it's the catch-all path. For any user who already has ≥1 known install, that means installRows = knownInstalls forever, and a new org grant only surfaces if a membership/member webhook fires and isn't missed. That was previously sign-in's whole job per the comment above it ("including orgs where they were added as admin after a different teammate created the install"). Either scope this PR to also handle that caller, or update the JSDoc/comment to document that sign-in and sweep no longer discover new installs, only revalidate known ones - right now the code silently does the latter while the comments still promise the former.
There was a problem hiding this comment.
Good call — I went with the documentation option. Pushed 8f62a4e: the JSDoc in maintainer-discover.ts now states sign-in + cron only revalidate known installs (webhook triggers pass installationId and pick up new grants; first-discovery falls back to a full scan), and the profile.ts sign-in comment was updated to match instead of promising cross-install discovery.
|
@jakharmonika364 re: the sign-in gap — I went with documenting the behavior rather than expanding sign-in scope, in 8f62a4e:
All three webhook callers (process-installation-event.ts transferred path, both handlers in process-membership-events.ts) already resolve and pass installationId, so new grants are still discovered in real time there. |
Summary
Fixes #784 — the daily cron sweep ran unbounded O(users x installs x repos) GitHub API calls per tick, enabling cross-installation rate limit exhaustion.
Vulnerability
The \maintainer-discover\ function had three critical flaws:
Fix
Scoped installations (primary fix)
Changed \discoverForUser\ to query installations through the \github_installation_users\ junction table with a join to \github_installations, so only installations the user already has a relationship with are checked.
Sweep improvements
Changes
Test Plan