diff --git a/apps/api/src/plugins/auth.ts b/apps/api/src/plugins/auth.ts index 6697336c..914f3a9d 100644 --- a/apps/api/src/plugins/auth.ts +++ b/apps/api/src/plugins/auth.ts @@ -96,6 +96,9 @@ const AGENT_KEY_SECRETS = [ "OPENAI_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN", "COPILOT_GITHUB_TOKEN", + "GEMINI_API_KEY", + "GOOGLE_CLOUD_PROJECT", + "CLAUDE_VERTEX_PROJECT_ID", ]; let _setupCompleteCache: { value: boolean; expires: number } | null = null; diff --git a/apps/api/src/routes/github-token.test.ts b/apps/api/src/routes/github-token.test.ts index cade128b..89c2d572 100644 --- a/apps/api/src/routes/github-token.test.ts +++ b/apps/api/src/routes/github-token.test.ts @@ -136,7 +136,12 @@ describe("POST /api/github-token/rotate", () => { const body = res.json(); expect(body.success).toBe(true); expect(body.user).toEqual({ login: "newuser", name: "New User" }); - expect(mockStoreSecret).toHaveBeenCalledWith("GITHUB_TOKEN", "ghp_newvalidtoken", "global"); + expect(mockStoreSecret).toHaveBeenCalledWith( + "GITHUB_TOKEN", + "ghp_newvalidtoken", + "global", + undefined, + ); }); it("rejects an invalid token without storing it", async () => { diff --git a/apps/api/src/routes/github-token.ts b/apps/api/src/routes/github-token.ts index 3a2a7b16..f62ac7a6 100644 --- a/apps/api/src/routes/github-token.ts +++ b/apps/api/src/routes/github-token.ts @@ -156,7 +156,7 @@ export async function githubTokenRoutes(rawApp: FastifyInstance) { const user = (await res.json()) as { login: string; name: string }; - await storeSecret("GITHUB_TOKEN", token.trim(), "global"); + await storeSecret("GITHUB_TOKEN", token.trim(), "global", req.user?.workspaceId); return reply.send({ success: true, diff --git a/apps/api/src/routes/setup.ts b/apps/api/src/routes/setup.ts index b5b7734b..b03e5408 100644 --- a/apps/api/src/routes/setup.ts +++ b/apps/api/src/routes/setup.ts @@ -556,7 +556,11 @@ export async function setupRoutes(rawApp: FastifyInstance) { const [, owner, repo] = match; const headers: Record = { "User-Agent": "Optio" }; let repoToken: string | null = token ?? null; - if (!repoToken) repoToken = await retrieveSecret("GITHUB_TOKEN").catch(() => null); + if (!repoToken) { + repoToken = await retrieveSecret("GITHUB_TOKEN", "global", req.user?.workspaceId).catch( + () => null, + ); + } if (!repoToken && isGitHubAppConfigured()) { repoToken = await getInstallationToken().catch(() => null); } diff --git a/apps/api/src/server.test.ts b/apps/api/src/server.test.ts index d63778c0..f2ec1600 100644 --- a/apps/api/src/server.test.ts +++ b/apps/api/src/server.test.ts @@ -203,13 +203,16 @@ describe("error handler", () => { describe("Zod error sanitization", () => { const originalNodeEnv = process.env.NODE_ENV; + const originalAuthDisabled = process.env.OPTIO_AUTH_DISABLED; afterEach(() => { process.env.NODE_ENV = originalNodeEnv; + process.env.OPTIO_AUTH_DISABLED = originalAuthDisabled; }); it("returns field names only for Zod errors in production", async () => { process.env.NODE_ENV = "production"; + process.env.OPTIO_AUTH_DISABLED = "true"; const testApp = await buildServer(); // Use /api/setup/ path to bypass auth middleware @@ -240,6 +243,7 @@ describe("Zod error sanitization", () => { it("returns full Zod error details in development", async () => { process.env.NODE_ENV = "development"; + process.env.OPTIO_AUTH_DISABLED = "true"; const testApp = await buildServer(); testApp.post("/api/setup/test-zod-dev", async () => {