diff --git a/src/api/routes.ts b/src/api/routes.ts index 7908188a13..2368be675b 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -6110,6 +6110,13 @@ function canSessionAccessPath(env: Env, identity: Extract { expect((await app.request(SETTINGS_A, { headers: { cookie } }, env)).status).toBe(200); expect((await app.request(SETTINGS_B, { headers: { cookie } }, env)).status).toBe(403); }); + + it("any authenticated session reaches registration-readiness / gittensor-config-recommendation for any repo (#8654)", async () => { + // These two advisory routes are intentionally open to any logged-in user (no per-repo ownership scope), but + // were omitted from the session allowlist, so every real non-operator browser session got 403 on the owner + // panel's only two data calls. charlie maintains nothing here, yet must reach both for an arbitrary repo. + const { app, env } = await setup(); + const { token } = await createSessionForGitHubUser(env, { login: "charlie", id: 999 }); + const cookie = `loopover_session=${token}`; + expect((await app.request("/v1/repos/alice/repo-a/registration-readiness", { headers: { cookie } }, env)).status).toBe(200); + expect((await app.request("/v1/repos/alice/repo-a/gittensor-config-recommendation", { headers: { cookie } }, env)).status).toBe(200); + }); }); describe("access boundary: contributor (miner) data is self-scoped", () => { diff --git a/test/unit/merge-train.test.ts b/test/unit/merge-train.test.ts index d7db0719af..57ba0c6b02 100644 --- a/test/unit/merge-train.test.ts +++ b/test/unit/merge-train.test.ts @@ -132,6 +132,18 @@ describe("shouldWaitForOlderSiblings (#selfhost-merge-train)", () => { expect(decide(110, "2026-07-07T11:00:00.000Z", siblings, NOW, { thisPrLinkedIssues: [1], thisPrChangedFiles: ["package-lock.json", "dist/bundle.js"] })).toEqual({ wait: false }); }); + it("does NOT treat a shared non-npm canonical lockfile (poetry.lock/go.sum) as meaningful overlap (#8647)", () => { + // The hand-rolled 4-name regex only knew package-lock/yarn/pnpm/Cargo, so these forced a spurious wait; + // delegating to the canonical isLockfile covers all 24+ formats. + const siblings: MergeTrainSibling[] = [{ number: 105, createdAt: "2026-07-07T10:00:00.000Z", linkedIssues: [99], changedFiles: ["poetry.lock", "backend/go.sum"] }]; + expect(decide(110, "2026-07-07T11:00:00.000Z", siblings, NOW, { thisPrLinkedIssues: [1], thisPrChangedFiles: ["poetry.lock", "backend/go.sum"] })).toEqual({ wait: false }); + }); + + it("does NOT treat a shared vendored-directory path (vendor/third_party) as meaningful overlap (#8647)", () => { + const siblings: MergeTrainSibling[] = [{ number: 105, createdAt: "2026-07-07T10:00:00.000Z", linkedIssues: [99], changedFiles: ["vendor/lib/x.go", "third_party/pkg/y.js"] }]; + expect(decide(110, "2026-07-07T11:00:00.000Z", siblings, NOW, { thisPrLinkedIssues: [1], thisPrChangedFiles: ["vendor/lib/x.go", "third_party/pkg/y.js"] })).toEqual({ wait: false }); + }); + it("a sibling with no linkedIssues field at all (undefined) can still match via a shared changed file", () => { const siblings: MergeTrainSibling[] = [{ number: 105, createdAt: "2026-07-07T10:00:00.000Z", changedFiles: ["src/a.ts"] }]; expect(decide(110, "2026-07-07T11:00:00.000Z", siblings, NOW, { thisPrLinkedIssues: [1], thisPrChangedFiles: ["src/a.ts"] })).toEqual({ wait: true, blockingPr: 105 });