diff --git a/server/src/__tests__/environment-selection-route-guards.test.ts b/server/src/__tests__/environment-selection-route-guards.test.ts index 0f36d4e512..7a9fb2c39e 100644 --- a/server/src/__tests__/environment-selection-route-guards.test.ts +++ b/server/src/__tests__/environment-selection-route-guards.test.ts @@ -117,6 +117,7 @@ function buildApp(routerFactory: (app: express.Express) => void) { (req as any).actor = { type: "board", userId: "user-1", + companyIds: ["company-1"], source: "local_implicit", }; next(); @@ -170,6 +171,10 @@ describe.sequential("execution environment route guards", () => { mockProjectService.createWorkspace.mockReset(); mockProjectService.remove.mockReset(); mockProjectService.resolveByReference.mockReset(); + mockProjectService.resolveByReference.mockResolvedValue({ + ambiguous: false, + project: { id: "project-1" }, + }); mockProjectService.listWorkspaces.mockReset(); mockIssueService.create.mockReset(); mockIssueService.getById.mockReset(); diff --git a/server/src/__tests__/project-routes-env.test.ts b/server/src/__tests__/project-routes-env.test.ts index d68576a73f..4cb93dc2e8 100644 --- a/server/src/__tests__/project-routes-env.test.ts +++ b/server/src/__tests__/project-routes-env.test.ts @@ -158,7 +158,7 @@ describe("project env routes", () => { explanation: "Allowed by test mock.", }); mockGetTelemetryClient.mockReturnValue({ track: vi.fn() }); - mockProjectService.resolveByReference.mockResolvedValue({ ambiguous: false, project: null }); + mockProjectService.resolveByReference.mockResolvedValue({ ambiguous: false, project: buildProject() }); mockProjectService.createWorkspace.mockResolvedValue(null); mockProjectService.listWorkspaces.mockResolvedValue([]); mockEnvironmentService.getById.mockReset(); diff --git a/server/src/__tests__/project-workspace-managed-sandbox-routes.test.ts b/server/src/__tests__/project-workspace-managed-sandbox-routes.test.ts index 5623fc6b07..b6324d4e26 100644 --- a/server/src/__tests__/project-workspace-managed-sandbox-routes.test.ts +++ b/server/src/__tests__/project-workspace-managed-sandbox-routes.test.ts @@ -203,7 +203,7 @@ describe("project workspace host-path floor", () => { explanation: "Allowed by test mock.", }); mockGetTelemetryClient.mockReturnValue({ track: vi.fn() }); - mockProjectService.resolveByReference.mockResolvedValue({ ambiguous: false, project: null }); + mockProjectService.resolveByReference.mockResolvedValue({ ambiguous: false, project: buildProject() }); mockProjectService.getById.mockResolvedValue(buildProject()); mockProjectService.create.mockResolvedValue(buildProject()); mockProjectService.createWorkspace.mockResolvedValue(buildWorkspace()); diff --git a/server/src/routes/projects.ts b/server/src/routes/projects.ts index 9d20e4d882..7a5d814935 100644 --- a/server/src/routes/projects.ts +++ b/server/src/routes/projects.ts @@ -116,7 +116,11 @@ export function projectRoutes(db: Db) { if (req.actor.type === "agent" && req.actor.companyId) { return req.actor.companyId; } - return null; + // A single-company actor (the common self-hosted case) has an unambiguous + // company context without a `?companyId=` query — shortnames only resolve + // inside one company anyway, so require exactly one. + const actorCompanyIds = req.actor.companyIds ?? []; + return actorCompanyIds.length === 1 ? actorCompanyIds[0] : null; } async function normalizeProjectReference(req: Request, rawId: string) {