Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
NEXT_PUBLIC_BACKEND_URL=
NEXT_PUBLIC_GUARDRAILS_URL =

GUARDRAILS_TOKEN=
Comment on lines +1 to +4
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix .env.example formatting issues.

Static analysis flagged several formatting problems:

  • Lines 1-2 have trailing whitespace
  • Line 2 has spaces around the = sign (should be NEXT_PUBLIC_GUARDRAILS_URL=)
  • Missing trailing newline at end of file

Some environment variable parsers are sensitive to these formatting issues.

Proposed fix
-NEXT_PUBLIC_BACKEND_URL= 
-NEXT_PUBLIC_GUARDRAILS_URL = 
+NEXT_PUBLIC_BACKEND_URL=
+NEXT_PUBLIC_GUARDRAILS_URL=
 
 GUARDRAILS_TOKEN=
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
NEXT_PUBLIC_BACKEND_URL=
NEXT_PUBLIC_GUARDRAILS_URL =
GUARDRAILS_TOKEN=
NEXT_PUBLIC_BACKEND_URL=
NEXT_PUBLIC_GUARDRAILS_URL=
GUARDRAILS_TOKEN=
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 1-1: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 1-1: [TrailingWhitespace] Trailing whitespace detected

(TrailingWhitespace)


[warning] 2-2: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 2-2: [TrailingWhitespace] Trailing whitespace detected

(TrailingWhitespace)


[warning] 4-4: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.example around lines 1 - 4, Remove trailing whitespace from the first
two lines, normalize the assignment for NEXT_PUBLIC_GUARDRAILS_URL by removing
spaces around the = so it reads exactly NEXT_PUBLIC_GUARDRAILS_URL=, ensure all
other keys (NEXT_PUBLIC_BACKEND_URL, GUARDRAILS_TOKEN) use the same no-space
format (KEY=) and add a final newline at the end of the file so the file ends
with a single newline character.

44 changes: 44 additions & 0 deletions app/api/apikeys/verify/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { NextRequest, NextResponse } from 'next/server';

const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent default backend port.

This file defaults to http://localhost:8000, while all other route handlers in this PR default to http://localhost:8001. This inconsistency could cause confusion during local development.

Proposed fix for consistency
-const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
+const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8001';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8001';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/apikeys/verify/route.ts` at line 3, The default backend URL in this
file uses the variable backendUrl set to 'http://localhost:8000', which is
inconsistent with other route handlers; update the default to
'http://localhost:8001' by modifying the backendUrl initialization in route.ts
so it matches the rest of the PR and local development environment.


export async function GET(request: NextRequest) {
try {
// Get the API key from request headers
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY header' },
{ status: 401 }
);
}

// Forward the request to the actual backend
const url = `${backendUrl}/api/v1/apikeys/verify`;

const response = await fetch(url, {
method: 'GET',
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});

// Handle empty responses (204 No Content, etc.)
const text = await response.text();
const data = text ? JSON.parse(text) : {};

// Return the response with the same status code
if (!response.ok) {
return NextResponse.json(data, { status: response.status });
}

return NextResponse.json(data, { status: response.status });
} catch (error: any) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error.message },
{ status: 500 }
);
}
}
157 changes: 157 additions & 0 deletions app/api/guardrails/ban_lists/[ban_list_id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { NextResponse } from 'next/server';

const backendUrl = process.env.NEXT_PUBLIC_GUARDRAILS_URL || 'http://localhost:8001';

export async function GET(
request: Request,
{ params }: { params: Promise<{ ban_list_id: string }> }
) {
const { ban_list_id } = await params;
const apiKey = request.headers.get('X-API-KEY');

if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY header' },
{ status: 401 }
);
}

try {
const url = `${backendUrl}/api/v1/guardrails/ban_lists/${ban_list_id}`;

console.log('[GET /api/guardrails/ban_lists/[ban_list_id]] Forwarding to:', url);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent log paths within the same file.

Line 22 uses ban_lists (plural) but lines 31, 37, 40 use ban_list (singular). Standardize to plural for consistency with the route path.

Proposed fix: Standardize to plural form

Apply consistent naming across all log statements. For example:

-    console.log('[GET /api/guardrails/ban_list/[ban_list_id]] Backend response status:', response.status, response.statusText);
+    console.log('[GET /api/guardrails/ban_lists/[ban_list_id]] Backend response status:', response.status, response.statusText);

Similar fixes needed for lines 37, 40, 74-76, 86, 88, 92, 95, 126, 136, 142, 145.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/guardrails/ban_lists/`[ban_list_id]/route.ts at line 22, The
console.log messages in route.ts use inconsistent path names ("ban_list" vs
"ban_lists"); update all logging strings in this file that reference the route
(e.g., the console.log at the shown diff and the other logs referenced around
the same handler) to use the plural "ban_lists" to match the actual route path;
search for occurrences of "ban_list" in this module (including the logs called
near the forwarding, response, and error messages) and replace them with
"ban_lists" so all console/debug statements are consistent with the route.


const response = await fetch(url, {
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});

console.log('[GET /api/guardrails/ban_list/[ban_list_id]] Backend response status:', response.status, response.statusText);

// Handle empty responses (204 No Content, etc.)
const text = await response.text();
const data = text ? JSON.parse(text) : {};

console.log('[GET /api/guardrails/ban_list/[ban_list_id]] Backend response data:', JSON.stringify(data, null, 2));

if (!response.ok) {
console.error('[GET /api/guardrails/ban_list/[ban_list_id]] Backend error:', response.status, data);
return NextResponse.json(data, { status: response.status });
}

return NextResponse.json(data, { status: response.status });
} catch (error: any) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error.message },
{ status: 500 }
);
}
}

export async function PUT(
request: Request,
{ params }: { params: Promise<{ ban_list_id: string }> }
) {
const { ban_list_id } = await params;
const apiKey = request.headers.get('X-API-KEY');

if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY header' },
{ status: 401 }
);
}

try {
// Get the JSON body from the request
const body = await request.json();

const url = `${backendUrl}/api/v1/guardrails/ban_lists/${ban_list_id}`;

console.log('[PUT /api/guardrails/ban_list/[ban_list_id]] Forwarding to:', url);
console.log('[PUT /api/guardrails/ban_list/[ban_list_id]] Body:', JSON.stringify(body, null, 2));

Comment on lines +75 to +76
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid logging full request body in production.

Same concern as other routes—logging complete request bodies could expose sensitive data in production logs.

Proposed fix
     console.log('[PUT /api/guardrails/ban_lists/[ban_list_id]] Forwarding to:', url);
-    console.log('[PUT /api/guardrails/ban_list/[ban_list_id]] Body:', JSON.stringify(body, null, 2));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log('[PUT /api/guardrails/ban_list/[ban_list_id]] Body:', JSON.stringify(body, null, 2));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/guardrails/ban_lists/`[ban_list_id]/route.ts around lines 75 - 76,
The console.log call that prints the full request body in the PUT handler (the
line containing "console.log('[PUT /api/guardrails/ban_list/[ban_list_id]]
Body:'...") should not emit full request bodies in production; remove this
unconditional logging and either (a) restrict it to non-production environments
(check process.env.NODE_ENV !== 'production' before logging), or (b) replace it
with a structured logger that redacts sensitive fields or logs only necessary
metadata (e.g., ban_list_id and operation type). Update the PUT route handler to
use one of these approaches so full request payloads are not written to
production logs.

const response = await fetch(url, {
method: 'PUT',
body: JSON.stringify(body),
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});

console.log('[PUT /api/guardrails/ban_list/[ban_list_id]] Backend response status:', response.status, response.statusText);

// Handle empty responses (204 No Content, etc.)
const text = await response.text();
const data = text ? JSON.parse(text) : { success: true };

console.log('[PUT /api/guardrails/ban_list/[ban_list_id]] Backend response data:', JSON.stringify(data, null, 2));

if (!response.ok) {
console.error('[PUT /api/guardrails/ban_list/[ban_list_id]] Backend error:', response.status, data);
return NextResponse.json(data, { status: response.status });
}

return NextResponse.json(data, { status: response.status });
} catch (error: any) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error.message },
{ status: 500 }
);
}
}

export async function DELETE(
request: Request,
{ params }: { params: Promise<{ ban_list_id: string }> }
) {
const { ban_list_id } = await params;
const apiKey = request.headers.get('X-API-KEY');

if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY header' },
{ status: 401 }
);
}

try {
const url = `${backendUrl}/api/v1/guardrails/ban_lists/${ban_list_id}`;

console.log('[DELETE /api/guardrails/ban_lists/[ban_list_id]] Forwarding to:', url);

const response = await fetch(url, {
method: 'DELETE',
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});

console.log('[DELETE /api/guardrails/ban_list/[ban_list_id]] Backend response status:', response.status, response.statusText);

// Handle empty responses (204 No Content, etc.)
const text = await response.text();
const data = text ? JSON.parse(text) : { success: true };

console.log('[DELETE /api/guardrails/ban_list/[ban_list_id]] Backend response data:', JSON.stringify(data, null, 2));

if (!response.ok) {
console.error('[DELETE /api/guardrails/ban_list/[ban_list_id]] Backend error:', response.status, data);
return NextResponse.json(data, { status: response.status });
}

return NextResponse.json(data, { status: response.status });
} catch (error: any) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error.message },
{ status: 500 }
);
}
}
104 changes: 104 additions & 0 deletions app/api/guardrails/ban_lists/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { NextRequest, NextResponse } from 'next/server';

const backendUrl = process.env.NEXT_PUBLIC_GUARDRAILS_URL || 'http://localhost:8001';

export async function GET(request: NextRequest) {
try {
// Get the Kaapi API key from request headers
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY header' },
{ status: 401 }
);
}

const url = `${backendUrl}/api/v1/guardrails/ban_lists`;

console.log('[GET /api/guardrails/ban_list] Forwarding to:', url);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent log path: singular vs plural.

Log messages use ban_list (singular) but the actual route path is ban_lists (plural). This inconsistency could cause confusion when debugging.

Proposed fix: Use consistent plural naming
-    console.log('[GET /api/guardrails/ban_list] Forwarding to:', url);
+    console.log('[GET /api/guardrails/ban_lists] Forwarding to:', url);

Apply similar fixes to other log statements in this file (lines 29, 35, 39, 69, 70, 82, 88, 92).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log('[GET /api/guardrails/ban_list] Forwarding to:', url);
console.log('[GET /api/guardrails/ban_lists] Forwarding to:', url);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/guardrails/ban_lists/route.ts` at line 18, Log messages in route
handler use the singular string '[GET /api/guardrails/ban_list]' which is
inconsistent with the actual route path 'ban_lists'; update all occurrences of
the literal 'ban_list' in console.log (and any other logging calls) within this
file to 'ban_lists' so logs match the route (search for the exact string '[GET
/api/guardrails/ban_list]' and similar variants and replace with '[GET
/api/guardrails/ban_lists]'); apply the same change to the other reported log
statements in this file to keep naming consistent.


// Forward the request to the actual backend
const response = await fetch(url, {
method: 'GET',
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});

console.log('[GET /api/guardrails/ban_list] Backend response status:', response.status, response.statusText);

// Handle empty responses (204 No Content, etc.)
const text = await response.text();
const data = text ? JSON.parse(text) : { data: [] };

console.log('[GET /api/guardrails/ban_list] Backend response data:', JSON.stringify(data, null, 2));

// Return the response with the same status code
if (!response.ok) {
console.error('[GET /api/guardrails/ban_list] Backend error:', response.status, data);
return NextResponse.json(data, { status: response.status });
}

return NextResponse.json(data, { status: response.status });
} catch (error: any) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error.message },
{ status: 500 }
);
}
}

export async function POST(request: NextRequest) {
try {
// Get the Kaapi API key from request headers
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY header' },
{ status: 401 }
);
}

// Get the JSON body from the request
const body = await request.json();

const url = `${backendUrl}/api/v1/guardrails/ban_lists`;

console.log('[POST /api/guardrails/ban_list] Forwarding to:', url);
console.log('[POST /api/guardrails/ban_list] Body:', JSON.stringify(body, null, 2));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid logging full request body in production.

Same concern as the validators/configs route—logging complete request bodies could expose sensitive data.

Proposed fix
     console.log('[POST /api/guardrails/ban_lists] Forwarding to:', url);
-    console.log('[POST /api/guardrails/ban_list] Body:', JSON.stringify(body, null, 2));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/guardrails/ban_lists/route.ts` at line 70, Remove the console.log
that prints the entire request body in the POST /api/guardrails/ban_list handler
and replace it with a safe log or no-op: either use the existing structured
logger (e.g., processLogger.debug) to log only non-sensitive metadata (request
id, user id, IP) or mask/omit sensitive fields from the body before logging;
alternatively gate the detailed logging behind a non-production check (NODE_ENV
!== 'production') and ensure the symbol "body" in the route handler is not fully
serialized in production.


// Forward the request to the actual backend
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(body),
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});

console.log('[POST /api/guardrails/ban_list] Backend response status:', response.status, response.statusText);

// Handle empty responses (204 No Content, etc.)
const text = await response.text();
const data = text ? JSON.parse(text) : { success: true };

console.log('[POST /api/guardrails/ban_list] Backend response data:', JSON.stringify(data, null, 2));

// Return the response with the same status code
if (!response.ok) {
console.error('[POST /api/guardrails/ban_list] Backend error:', response.status, data);
return NextResponse.json(data, { status: response.status });
}

return NextResponse.json(data, { status: response.status });
} catch (error: any) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error.message },
{ status: 500 }
);
}
}
Loading