diff --git a/openspec/changes/code-review-fix/tasks.md b/openspec/changes/code-review-fix/tasks.md index 0be4f62..ce982bf 100644 --- a/openspec/changes/code-review-fix/tasks.md +++ b/openspec/changes/code-review-fix/tasks.md @@ -21,7 +21,7 @@ - [x] 3.1 `[sonnet]` Create `src/middleware.ts` with API key auth middleware: read `API_KEY` env var, check `X-API-Key` header on all `/api/*` routes except `/api/health`, return 401 if invalid - [x] 3.2 `[sonnet]` Add FastAPI `Depends()` API key dependency in `services/ml/app/main.py`: read `API_KEY` env var, check `X-API-Key` header, exempt `/health` endpoint -- [ ] 3.3 `[sonnet]` Update all Next.js proxy routes to forward `X-API-Key` header to ML service +- [x] 3.3 `[sonnet]` Update all Next.js proxy routes to forward `X-API-Key` header to ML service - [ ] 3.4 `[haiku]` Add `API_KEY` to `.env.example` with placeholder value and instructions ## 4. API Route Hardening (Next.js) diff --git a/src/app/api/model/info/route.ts b/src/app/api/model/info/route.ts index 4dfd3c5..756a064 100644 --- a/src/app/api/model/info/route.ts +++ b/src/app/api/model/info/route.ts @@ -14,6 +14,7 @@ export async function GET(request: NextRequest) { method: 'GET', headers: { 'Content-Type': 'application/json', + 'X-API-Key': process.env.API_KEY || '', }, signal: controller.signal, }); diff --git a/src/app/api/model/load/route.ts b/src/app/api/model/load/route.ts index 793bcbb..75c8e6a 100644 --- a/src/app/api/model/load/route.ts +++ b/src/app/api/model/load/route.ts @@ -12,7 +12,7 @@ export async function POST(request: NextRequest) { const response = await fetch(`${INFERENCE_API_URL}/model/load`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, body: JSON.stringify(body), signal: controller.signal, }); diff --git a/src/app/api/patterns/available/route.ts b/src/app/api/patterns/available/route.ts index 4669ec9..4f95a4d 100644 --- a/src/app/api/patterns/available/route.ts +++ b/src/app/api/patterns/available/route.ts @@ -10,7 +10,7 @@ export async function GET(_request: NextRequest) { try { const response = await fetch(`${INFERENCE_API_URL}/patterns/available`, { method: 'GET', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, signal: controller.signal, }); clearTimeout(timeoutId); diff --git a/src/app/api/patterns/detect/route.ts b/src/app/api/patterns/detect/route.ts index 483cc88..5d9a929 100644 --- a/src/app/api/patterns/detect/route.ts +++ b/src/app/api/patterns/detect/route.ts @@ -13,7 +13,7 @@ export async function POST(request: NextRequest) { const response = await fetch(`${INFERENCE_API_URL}/patterns/detect`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, body: JSON.stringify(body), signal: controller.signal, }); diff --git a/src/app/api/predict/batch/route.ts b/src/app/api/predict/batch/route.ts index c0761f2..cf0ec82 100644 --- a/src/app/api/predict/batch/route.ts +++ b/src/app/api/predict/batch/route.ts @@ -16,6 +16,7 @@ export async function POST(request: NextRequest) { method: 'POST', headers: { 'Content-Type': 'application/json', + 'X-API-Key': process.env.API_KEY || '', }, body: JSON.stringify(body), signal: controller.signal, diff --git a/src/app/api/predict/route.ts b/src/app/api/predict/route.ts index 4928de1..ef00249 100644 --- a/src/app/api/predict/route.ts +++ b/src/app/api/predict/route.ts @@ -16,6 +16,7 @@ export async function POST(request: NextRequest) { method: 'POST', headers: { 'Content-Type': 'application/json', + 'X-API-Key': process.env.API_KEY || '', }, body: JSON.stringify(body), signal: controller.signal, diff --git a/src/app/api/training/active/route.ts b/src/app/api/training/active/route.ts index b62aa36..c7b0260 100644 --- a/src/app/api/training/active/route.ts +++ b/src/app/api/training/active/route.ts @@ -10,7 +10,7 @@ export async function GET(_request: NextRequest) { try { const response = await fetch(`${INFERENCE_API_URL}/training/active`, { method: 'GET', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, signal: controller.signal, }); clearTimeout(timeoutId); diff --git a/src/app/api/training/build-dataset/route.ts b/src/app/api/training/build-dataset/route.ts index 22c0cbf..b34be3c 100644 --- a/src/app/api/training/build-dataset/route.ts +++ b/src/app/api/training/build-dataset/route.ts @@ -10,7 +10,7 @@ export async function POST() { try { const response = await fetch(`${INFERENCE_API_URL}/training/build-dataset`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, signal: controller.signal, }); clearTimeout(timeoutId); diff --git a/src/app/api/training/dataset-info/route.ts b/src/app/api/training/dataset-info/route.ts index 5aa9474..b6a8eb7 100644 --- a/src/app/api/training/dataset-info/route.ts +++ b/src/app/api/training/dataset-info/route.ts @@ -10,7 +10,7 @@ export async function GET(_request: NextRequest) { try { const response = await fetch(`${INFERENCE_API_URL}/training/dataset-info`, { method: 'GET', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, signal: controller.signal, }); clearTimeout(timeoutId); diff --git a/src/app/api/training/runs/[run_id]/route.ts b/src/app/api/training/runs/[run_id]/route.ts index 1ac3773..4bbd8a8 100644 --- a/src/app/api/training/runs/[run_id]/route.ts +++ b/src/app/api/training/runs/[run_id]/route.ts @@ -24,6 +24,7 @@ export async function DELETE( try { const response = await fetch(`${INFERENCE_API_URL}/training/runs/${run_id}`, { method: 'DELETE', + headers: { 'X-API-Key': process.env.API_KEY || '' }, signal: controller.signal, }); clearTimeout(timeoutId); diff --git a/src/app/api/training/runs/route.ts b/src/app/api/training/runs/route.ts index 215b18a..42ab14a 100644 --- a/src/app/api/training/runs/route.ts +++ b/src/app/api/training/runs/route.ts @@ -10,7 +10,7 @@ export async function GET(_request: NextRequest) { try { const response = await fetch(`${INFERENCE_API_URL}/training/runs`, { method: 'GET', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, signal: controller.signal, }); clearTimeout(timeoutId); diff --git a/src/app/api/training/start/route.ts b/src/app/api/training/start/route.ts index 4cbde69..0ed45f4 100644 --- a/src/app/api/training/start/route.ts +++ b/src/app/api/training/start/route.ts @@ -12,7 +12,7 @@ export async function POST(request: NextRequest) { const response = await fetch(`${INFERENCE_API_URL}/training/start`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.API_KEY || '' }, body: JSON.stringify(body), signal: controller.signal, });