fix: refreshGithubInstallations discovers re-installs for known accounts #68#239
fix: refreshGithubInstallations discovers re-installs for known accounts #68#239wonderwomancode wants to merge 1 commit into
Conversation
…unts #68 The Refresh button in the GitHub connect panel calls refreshGithubInstallations, which previously only updated metadata for installations already in the DB. If syncGithubInstallation was never called for an installation (e.g. setup_url redirect was interrupted, or user re-installed the App on the same GitHub account), the Refresh button returned an empty list. Add Phase 2 discovery: after refreshing existing rows, call listAllInstallations() and auto-claim any installation whose account.login matches an account already linked to this org. Two safety constraints prevent reintroducing the 2026-04-22 cross-tenant claim bug: 1. Only claim installs for account.login values already recorded under THIS org — never unknown accounts. 2. Skip any installation_id already owned by another org in DB. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
Quinn QA ReviewVerdict: REQUEST CHANGES
Test coverage findingsBLOCKER: Zero automated test coverage for the new Phase 2 security logic.
The 2026-04-22 cross-tenant data leak is explicitly cited as the historical motivation for constraints 1 and 2. Those constraints are the entire security guarantee of this PR. Without automated tests, any future refactor that accidentally widens the Regression risksLow overall. Phase 1 behavior is unchanged (same One subtle limitation: Phase 2 only works when Code quality and maintainabilityThe logic is clean and in-code comments are thorough. The phased approach with separate error boundaries is the right structure. The One growth note: Bugs / logic errorsNone found. The TOCTOU race between Security implicationsBoth constraints are correctly structured. Lain will go deeper — flagging the untested constraint coverage as the primary risk since the exploit this defends against already happened once. Blockers
Suggested follow-ups (non-blocking)
|
Summary
refreshGithubInstallationsPhase 2 discovery: The Refresh button previously calledrefreshGithubInstallationswhich only updated metadata for installations already in the DB. If a user re-installed the GitHub App on the same account (newinstallation_id, sameaccount.login), or ifsyncGithubInstallationwas interrupted during the setup_url redirect, the Refresh button returned an empty list.Added Phase 2: after refreshing existing rows, call
listAllInstallations()(App JWT, already inclient.ts) and auto-claim any GitHub installation whoseaccount.loginmatches an account already linked to this org's DB. Two safety constraints prevent reintroducing the 2026-04-22 cross-tenant claim bug:account.loginvalues already recorded under this org — never unknown accounts.installation_idalready owned by another org in DB.listAllInstallationsimport: Added to the import list (it was already inclient.tsbut unused here).requireAuthreturn captured: ChangedrequireAuth(context)(return ignored) toconst userId = requireAuth(context)souserIdis available forinstalledByUserIdandgrantInstallationAccessin Phase 2.Test plan
syncGithubInstallationruns via setup_url → install appears in picker ✅ (unchanged)installation_idvia account_login matchlistAllInstallations()failure (simulate GitHub API down) → non-fatal, mutation still returns existing DB recordsCloses #68
🤖 Generated with Claude Code