Problem
Auth validation is currently implemented in two inconsistent patterns:
agents.ts — Uses a proper Fastify preHandler hook (apiKeyAuth) that does format check + DB lookup. This is the correct idiomatic approach.
chat.ts, audio.ts, models.ts, embeddings.ts, responses.ts, files.ts — Inline validateAuth() (shape-only) ± agentStore.validateKey() inside handler bodies.
The inline pattern is error-prone — it caused #149 (comment) where the audio endpoint accepted unregistered keys because the DB check was missing.
Proposed Solution
- Extract
apiKeyAuth from agents.ts into a shared module (e.g. src/middleware/auth.ts)
- Apply it as a
preHandler on all authenticated routes
- Remove inline
validateAuth() + agentStore.validateKey() calls from handler bodies
- Single source of truth for auth logic — new routes automatically get proper validation
Benefits
- Prevents entire class of "forgot to add DB check" bugs
- Follows Fastify idioms (
preHandler hooks)
- Reduces code duplication across 6+ route files
- Makes auth policy changes atomic (one place to update)
Files to Update
src/routes/chat.ts
src/routes/audio.ts
src/routes/models.ts
src/routes/embeddings.ts
src/routes/responses.ts
src/routes/files.ts
src/routes/agents.ts (extract, keep using)
- New:
src/middleware/auth.ts
Problem
Auth validation is currently implemented in two inconsistent patterns:
agents.ts— Uses a proper FastifypreHandlerhook (apiKeyAuth) that does format check + DB lookup. This is the correct idiomatic approach.chat.ts,audio.ts,models.ts,embeddings.ts,responses.ts,files.ts— InlinevalidateAuth()(shape-only) ±agentStore.validateKey()inside handler bodies.The inline pattern is error-prone — it caused #149 (comment) where the audio endpoint accepted unregistered keys because the DB check was missing.
Proposed Solution
apiKeyAuthfromagents.tsinto a shared module (e.g.src/middleware/auth.ts)preHandleron all authenticated routesvalidateAuth()+agentStore.validateKey()calls from handler bodiesBenefits
preHandlerhooks)Files to Update
src/routes/chat.tssrc/routes/audio.tssrc/routes/models.tssrc/routes/embeddings.tssrc/routes/responses.tssrc/routes/files.tssrc/routes/agents.ts(extract, keep using)src/middleware/auth.ts