fix: secure /api/ai endpoint and remove debug routes

- Add auth to /api/ai via requireFamily middleware
- Remove /api/ai and /api/auth/debug from public routes
- Delete debug/test routes that expose internal state

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Manohar Gupta 2026-05-17 16:41:47 +05:30
parent 797c970d81
commit c459b4411a
4 changed files with 14 additions and 48 deletions

View file

@ -1 +0,0 @@
import { NextResponse } from "next/server"; export async function GET() { return NextResponse.json({ test: "success" }); }

View file

@ -2,6 +2,7 @@ import { NextResponse } from "next/server";
import { sql } from "@/db";
import { detectMedicalIntent, ESCALATION_RULES } from "@/lib/ai/medical-triggers";
import { logAudit } from "@/lib/audit";
import { requireFamily } from "@/lib/auth";
const LITELLM_URL = process.env.LITELLM_BASE_URL;
const LITELLM_KEY = process.env.LITELLM_API_KEY;
@ -13,6 +14,15 @@ export async function POST(request: Request) {
return NextResponse.json({ error: "AI service not configured" }, { status: 503 });
}
// Require authentication
const auth = await requireFamily();
if (!auth.success) {
return NextResponse.json({ error: auth.error }, { status: auth.status });
}
const session = auth.session!;
const familyId = session.familyId!;
const body = await request.json();
const { messages, childId } = body;
@ -25,11 +35,10 @@ export async function POST(request: Request) {
// HARD GUARDRAIL: Check for medical intent BEFORE calling LLM
const intent = detectMedicalIntent(lastUserMsg);
if (intent.isMedical) {
// Fetch pediatrician phone
const sessionToken = request.headers.get("cookie")?.match(/tia_session=([^;]+)/)?.[1] || "";
// Fetch pediatrician phone using familyId
const families = await sql`
SELECT pediatrician_phone FROM families
WHERE id IN (SELECT family_id FROM family_members WHERE user_id IN (SELECT user_id FROM sessions WHERE session_token = ${sessionToken}))
WHERE id = ${familyId}
LIMIT 1
`;
const pediatricianPhone = families[0]?.pediatrician_phone;
@ -49,6 +58,8 @@ export async function POST(request: Request) {
action: "ai_medical_redirect",
metadata: { category: intent.category, keyword: intent.matchedKeyword },
request,
userId: session.userId,
familyId,
});
return NextResponse.json({

View file

@ -1,42 +0,0 @@
import { NextResponse } from "next/server";
import { sql } from "@/db";
import { cookies } from "next/headers";
export async function GET() {
const sessionToken = (await cookies()).get("tia_session")?.value;
if (!sessionToken) {
return NextResponse.json({ error: "no cookie" });
}
// Get user from session
const sessions = await sql.unsafe(
`SELECT s.user_id FROM sessions s WHERE s.session_token = $1`,
[sessionToken]
);
const userId = sessions?.[0]?.user_id;
// Check families table
const families = await sql.unsafe(
`SELECT id, name FROM families ORDER BY created_at DESC LIMIT 5`
);
// Check family_members table
const members = await sql.unsafe(
`SELECT id, family_id, user_id, role FROM family_members ORDER BY created_at DESC LIMIT 5`
);
// Check children table
const children = await sql.unsafe(
`SELECT id, family_id, name FROM children ORDER BY created_at DESC LIMIT 5`
);
return NextResponse.json({
cookie: sessionToken?.slice(0, 20) + "...",
userId,
families,
members,
children
});
}

View file

@ -9,8 +9,6 @@ const publicRoutes = [
"/api/auth/signin",
"/api/admin/auth",
"/api/onboarding",
"/api/ai",
"/api/auth/debug",
];
// Protected API routes that need authentication