diff --git a/src/signals/settings-preview.ts b/src/signals/settings-preview.ts index 0a5774b499..8e58cac5d4 100644 --- a/src/signals/settings-preview.ts +++ b/src/signals/settings-preview.ts @@ -494,6 +494,7 @@ function activeMissingPermissions(settings: RepositorySettings, decision: Public if (!installation) return []; const missing = new Set(installation.missingPermissions); const active: string[] = []; + if (missing.has("pull_requests")) active.push("pull_requests"); // Comment/label output is gated on issues:write (Issues endpoints), not pull_requests:write. if (writesPrPublicSurface(settings, decision) && missing.has("issues")) active.push("issues"); if ((decision.willCheckRun || settings.checkRunMode === "enabled" || settings.gateCheckMode === "enabled") && missing.has("checks")) active.push("checks"); diff --git a/test/unit/settings-preview.test.ts b/test/unit/settings-preview.test.ts index e11a15d127..1086f5fd6a 100644 --- a/test/unit/settings-preview.test.ts +++ b/test/unit/settings-preview.test.ts @@ -166,9 +166,10 @@ describe("buildRepoSettingsPreview", () => { }); }); - it("requires only pull_requests:read for PR comment/label output (no PR write overprivilege)", () => { - // Installation grants issues:write (everything comment/label output actually needs) but is missing - // pull_requests; the app only reads PRs, so this must NOT be flagged as a comment/label blocker. + it("reports missing pull_requests:read without requiring PR write for PR comment/label output", () => { + // Installation grants issues:write (everything comment/label output actually writes with) but is missing + // pull_requests:read, which the app still requires to read PRs. This must be reported without + // regressing to the previous overbroad pull_requests:write requirement. const preview = buildRepoSettingsPreview({ ...base, settings: settings(), @@ -177,7 +178,13 @@ describe("buildRepoSettingsPreview", () => { }); expect(preview.installPreview.permissions.required).toContain("pull_requests: read"); expect(preview.installPreview.permissions.required).not.toContain("pull_requests: write"); - expect(preview.installPreview.permissions.missing).not.toContain("pull_requests"); + expect(preview.installPreview.permissions.missing).toContain("pull_requests"); + expect(preview.installPreview.permissions.status).toBe("needs_attention"); + expect(preview.installPreview.status).toBe("needs_attention"); + expect(preview.installPreview.checklist.find((item) => item.id === "permissions")).toMatchObject({ + status: "needs_attention", + summary: expect.stringContaining("pull_requests"), + }); }); it("explains a missing optional Checks: write permission only when check runs are enabled", () => {