feat: separate internal and external open-task listing traffic
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 8s
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 8s
This commit is contained in:
@@ -28,6 +28,37 @@ const MCP_AGENT_HEADERS = [
|
||||
"x-openai-agent",
|
||||
];
|
||||
|
||||
function resolveSourceIp(request: NextRequest) {
|
||||
return (
|
||||
request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ??
|
||||
request.headers.get("x-real-ip") ??
|
||||
"unknown"
|
||||
);
|
||||
}
|
||||
|
||||
function isPrivateIp(ip: string | undefined) {
|
||||
if (!ip) return false;
|
||||
const normalized = ip.trim().toLowerCase();
|
||||
if (!normalized || normalized === "unknown" || normalized === "::1" || normalized === "localhost") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized.startsWith("127.") || normalized.startsWith("10.") || normalized.startsWith("192.168.")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized.startsWith("172.")) {
|
||||
const secondOctet = Number(normalized.split(".")[1]);
|
||||
return secondOctet >= 16 && secondOctet <= 31;
|
||||
}
|
||||
|
||||
if (normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("fe80")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function normalizeActorId(value: string, fallback: string) {
|
||||
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9._:-]+/g, "_").replace(/_+/g, "_");
|
||||
return normalized.slice(0, 64) || fallback;
|
||||
@@ -72,6 +103,9 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
|
||||
case "list_open_tasks": {
|
||||
ListOpenTasksRequestSchema.parse(body);
|
||||
const actor = resolveActorFromMcpRequest(request);
|
||||
const sourceIp = resolveSourceIp(request);
|
||||
const isPublicIp = !isPrivateIp(sourceIp);
|
||||
const trafficAction = isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS_MCP" : "INTERNAL_LIST_OPEN_TASKS_MCP";
|
||||
|
||||
const tasks = await prisma.task.findMany({
|
||||
where: { status: TaskStatus.OPEN },
|
||||
@@ -95,7 +129,7 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
|
||||
|
||||
void sendTrafficAlert({
|
||||
level: "info",
|
||||
action: "EXTERNAL_LIST_OPEN_TASKS_MCP",
|
||||
action: trafficAction,
|
||||
surface: "mcp/list_open_tasks",
|
||||
actorType: actor.actorType,
|
||||
actorId: actor.actorId,
|
||||
@@ -104,11 +138,8 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
|
||||
metadata: {
|
||||
count: formattedTasks.length,
|
||||
source_tool: tool,
|
||||
source_ip: sourceIp,
|
||||
user_agent: request.headers.get("user-agent") ?? "unknown",
|
||||
source_ip:
|
||||
request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ??
|
||||
request.headers.get("x-real-ip") ??
|
||||
"unknown",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -117,13 +148,13 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
|
||||
createdAt: {
|
||||
gte: new Date(Date.now() - MCP_SURGE_WINDOW_MINUTES * 60 * 1000),
|
||||
},
|
||||
action: "EXTERNAL_LIST_OPEN_TASKS_MCP",
|
||||
action: trafficAction,
|
||||
},
|
||||
}).then((eventCount) => {
|
||||
if (eventCount > 0 && eventCount % MCP_SURGE_INTERVAL === 0) {
|
||||
void sendTrafficAlert({
|
||||
level: "warning",
|
||||
action: "EXTERNAL_LIST_OPEN_TASKS_SURGE",
|
||||
action: isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS_SURGE" : "INTERNAL_LIST_OPEN_TASKS_SURGE",
|
||||
surface: "mcp/list_open_tasks",
|
||||
actorType: "SYSTEM",
|
||||
actorId: "traffic-monitor",
|
||||
|
||||
@@ -49,6 +49,29 @@ function resolveSourceIp(request: Request) {
|
||||
);
|
||||
}
|
||||
|
||||
function isPrivateIp(ip: string | undefined) {
|
||||
if (!ip) return false;
|
||||
const normalized = ip.trim().toLowerCase();
|
||||
if (!normalized || normalized === "unknown" || normalized === "::1" || normalized === "localhost") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized.startsWith("127.") || normalized.startsWith("10.") || normalized.startsWith("192.168.")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized.startsWith("172.")) {
|
||||
const secondOctet = Number(normalized.split(".")[1]);
|
||||
return secondOctet >= 16 && secondOctet <= 31;
|
||||
}
|
||||
|
||||
if (normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("fe80")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isLikelyAIAgentUserAgent(userAgent: string) {
|
||||
const normalized = userAgent.toLowerCase();
|
||||
return AI_USER_AGENT_HINTS.some((token) => normalized.includes(token));
|
||||
@@ -83,6 +106,10 @@ function resolveExternalActor(request: Request) {
|
||||
}
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const sourceIp = resolveSourceIp(request);
|
||||
const isPublicIp = !isPrivateIp(sourceIp);
|
||||
const trafficAction = isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS" : "INTERNAL_LIST_OPEN_TASKS";
|
||||
|
||||
const tasks = await prisma.task.findMany({
|
||||
where: { status: TaskStatus.OPEN },
|
||||
orderBy: { created_at: "desc" },
|
||||
@@ -124,7 +151,7 @@ export async function GET(request: Request) {
|
||||
|
||||
void sendTrafficAlert({
|
||||
level: "info",
|
||||
action: "EXTERNAL_LIST_OPEN_TASKS",
|
||||
action: trafficAction,
|
||||
surface: "public-open-tasks",
|
||||
actorType: actor.actorType,
|
||||
actorId: actor.actorId,
|
||||
@@ -133,7 +160,7 @@ export async function GET(request: Request) {
|
||||
metadata: {
|
||||
source: "public-open-tasks",
|
||||
task_count: publicPayload.length,
|
||||
source_ip: resolveSourceIp(request),
|
||||
source_ip: sourceIp,
|
||||
user_agent: request.headers.get("user-agent") ?? "unknown",
|
||||
},
|
||||
});
|
||||
@@ -145,13 +172,13 @@ export async function GET(request: Request) {
|
||||
void prisma.auditEvent.count({
|
||||
where: {
|
||||
createdAt: { gte: surgeWindowStart },
|
||||
action: "EXTERNAL_LIST_OPEN_TASKS",
|
||||
action: trafficAction,
|
||||
},
|
||||
}).then((eventCount) => {
|
||||
if (eventCount > 0 && eventCount % 25 === 0) {
|
||||
void sendTrafficAlert({
|
||||
level: "warning",
|
||||
action: "EXTERNAL_LIST_OPEN_TASKS_SURGE",
|
||||
action: isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS_SURGE" : "INTERNAL_LIST_OPEN_TASKS_SURGE",
|
||||
surface: "public-open-tasks",
|
||||
actorType: "SYSTEM",
|
||||
actorId: "traffic-monitor",
|
||||
|
||||
Reference in New Issue
Block a user