Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NEXT_PUBLIC_BACKEND_URL=

GUARDRAIL_TOKEN=
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add trailing newline for POSIX compliance.

Per static analysis, the file is missing a blank line at the end. This is a minor formatting issue but good practice for POSIX-compliant text files.

Proposed fix
 NEXT_PUBLIC_BACKEND_URL=

-GUARDRAIL_TOKEN=
+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=
GUARDRAIL_TOKEN=
NEXT_PUBLIC_BACKEND_URL=
GUARDRAILS_TOKEN=
Suggested change
NEXT_PUBLIC_BACKEND_URL=
GUARDRAIL_TOKEN=
NEXT_PUBLIC_BACKEND_URL=
GUARDRAIL_TOKEN=
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 3-3: [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 - 3, The .env.example file is missing a trailing
newline; update the file so it ends with a single blank line (i.e., ensure there
is a newline character after the last line containing GUARDRAIL_TOKEN) to
satisfy POSIX newline conventions for files like NEXT_PUBLIC_BACKEND_URL and
GUARDRAIL_TOKEN.

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
Copy Markdown

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_BACKEND_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
Copy Markdown

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
Copy Markdown

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_BACKEND_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
Copy Markdown

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
Copy Markdown

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