chore: cleanup legacy OpenAI references, update CSP, verify build

- Add https://chatgpt.com to connect-src CSP directive for Codex OAuth token exchange
- Fix eslint no-explicit-any errors in codex-client.ts and provider.test.ts
- Fix unused variable warnings in authorize route
- All 118 tests pass, build succeeds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.6 committed 2026-04-06 00:42:46 +02:00
1 parent 5a71f9b36a
commit 50911ad801
4 files changed
+14 -14

No files matched your search

+2 -2
View File
@@ -8,8 +8,8 @@ import {
import { cookies } from "next/headers";
import { annotate } from "@/lib/logging/context";
export const GET = apiHandler(async (request: NextRequest) => {
const { user } = await requireAuth();
export const GET = apiHandler(async (_request: NextRequest) => {
await requireAuth();
const { verifier, challenge } = generatePKCE();
const state = generateState();
+8 -8
View File
@@ -12,7 +12,7 @@ vi.mock("@/lib/crypto", () => ({
}));
vi.mock("@/lib/ai/codex-oauth", () => ({
refreshAccessToken: vi.fn(),
encryptTokens: vi.fn((t: any) => ({ accessEncrypted: `enc:${t.accessToken}`, refreshEncrypted: `enc:${t.refreshToken}` })),
encryptTokens: vi.fn((t: { accessToken: string; refreshToken: string }) => ({ accessEncrypted: `enc:${t.accessToken}`, refreshEncrypted: `enc:${t.refreshToken}` })),
decryptTokens: vi.fn(),
}));
@@ -36,7 +36,7 @@ describe("resolveProvider", () => {
codexRefreshTokenEncrypted: "enc-refresh",
codexTokenExpiresAt: new Date(Date.now() + 3600000),
codexConnectionStatus: "connected",
} as any);
} as never);
const provider = await resolveProvider("user-123");
expect(provider.type).toBe("codex");
@@ -48,13 +48,13 @@ describe("resolveProvider", () => {
codexRefreshTokenEncrypted: null,
codexTokenExpiresAt: null,
codexConnectionStatus: "disconnected",
} as any);
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
adminAiKeyEncrypted: "enc-admin-key",
adminAiModel: "gpt-4o-mini",
adminAiBaseUrl: "https://api.openai.com/v1",
} as any);
} as never);
const provider = await resolveProvider("user-123");
expect(provider.type).toBe("admin-key");
@@ -64,11 +64,11 @@ describe("resolveProvider", () => {
vi.mocked(prisma.user.findUnique).mockResolvedValue({
codexAccessTokenEncrypted: null,
codexConnectionStatus: "disconnected",
} as any);
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
adminAiKeyEncrypted: null,
} as any);
} as never);
const provider = await resolveProvider("user-123");
expect(provider.type).toBe("none");
@@ -80,13 +80,13 @@ describe("resolveProvider", () => {
codexRefreshTokenEncrypted: "enc-refresh",
codexTokenExpiresAt: new Date(Date.now() - 1000),
codexConnectionStatus: "expired",
} as any);
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
adminAiKeyEncrypted: "enc-admin",
adminAiModel: "gpt-4o",
adminAiBaseUrl: "https://api.openai.com/v1",
} as any);
} as never);
const provider = await resolveProvider("user-123");
expect(provider.type).toBe("admin-key");
+3 -3
View File
@@ -57,11 +57,11 @@ export class CodexClient implements AIProvider {
private async parseResponse(res: Response): Promise<CompletionResult> {
const json = await res.json();
const messageOutput = json.output?.find(
(o: any) => o.type === "message",
const messageOutput = (json.output as Array<{ type: string; content?: Array<{ type: string; text?: string }> }>)?.find(
(o) => o.type === "message",
);
const textContent = messageOutput?.content?.find(
(c: any) => c.type === "output_text",
(c) => c.type === "output_text",
);
if (!textContent?.text) {
+1 -1
View File
@@ -108,7 +108,7 @@ export function proxy(request: NextRequest) {
const cspReportEndpoint = "/api/monitoring/csp-report";
const csp = isDev
? `default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://www.gravatar.com; connect-src 'self'; font-src 'self';`
: `default-src 'self'; script-src 'self' 'nonce-${nonce}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://www.gravatar.com; connect-src 'self' https://api.openai.com https://wbsapi.withings.net; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; worker-src 'self'; report-uri ${cspReportEndpoint}; report-to csp-endpoint;`;
: `default-src 'self'; script-src 'self' 'nonce-${nonce}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://www.gravatar.com; connect-src 'self' https://api.openai.com https://chatgpt.com https://wbsapi.withings.net; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; worker-src 'self'; report-uri ${cspReportEndpoint}; report-to csp-endpoint;`;
response.headers.set("Content-Security-Policy", csp);
// Production-only headers