Files
lunarfront-app/packages/backend/src/routes/v1/health.ts
Ryan Moon e65175ef19 Fix security issues: path traversal, typed errors, file validation
- Fix path traversal in file serve endpoint (validate company prefix, block ..)
- Add typed error classes: ValidationError, NotFoundError, ForbiddenError,
  ConflictError, StorageError
- Global error handler catches AppError subclasses with correct status codes
- 4xx logged as warn, 5xx as error with request ID
- File upload validates entityType whitelist, UUID format, category pattern
- Remove fragile string-matching error handling from routes
- Services throw typed errors instead of plain Error
- Health endpoint documented as intentionally public
2026-03-28 16:03:45 -05:00

34 lines
1023 B
TypeScript

import type { FastifyPluginAsync } from 'fastify'
import { sql } from 'drizzle-orm'
export const healthRoutes: FastifyPluginAsync = async (app) => {
// Intentionally public — no auth. Load balancers, Docker health checks, and monitoring need this.
app.get('/health', async (request, reply) => {
let dbStatus = 'disconnected'
let redisStatus = 'disconnected'
try {
await app.db.execute(sql`SELECT 1`)
dbStatus = 'connected'
} catch (err) {
request.log.error({ err }, 'Database health check failed')
}
try {
const pong = await app.redis.ping()
redisStatus = pong === 'PONG' ? 'connected' : 'disconnected'
} catch (err) {
request.log.error({ err }, 'Redis health check failed')
}
const healthy = dbStatus === 'connected' && redisStatus === 'connected'
reply.status(healthy ? 200 : 503).send({
status: healthy ? 'ok' : 'degraded',
db: dbStatus,
redis: redisStatus,
timestamp: new Date().toISOString(),
})
})
}