Backend Middleware

10 middleware modules in backend/src/middleware/. Execution order is critical — security middleware runs before business logic, and error handling wraps everything.

Middleware Pipeline

OrderFilePurposeConfig
1(built-in)Request logging + UUIDHono logger
2timeout.ts55-second request timeoutPrevents hung requests
3security.tsCSP, HSTS, X-Frame-Options headersMiddleware Stack
4(built-in)CORSHono CORS
5sanitization.tsXSS/injection prevention via DOMPurifyValidation Pattern
6rateLimiter.tsAuth: 5 req/15min, API: 100 req/minUpstash Redis
7auth.tsJWT verification and user contextAuthentication
8rbac.tsRole-based access control checksRBAC Authorization
9portal-auth.tsPortal token authenticationPortal
10appointment-portal-auth.tsAppointment portal token authAppointments
11auditLogger.tsAudit trail loggingAudit Logs
12errorHandler.tsCentralized error handling + Sentry captureError Handling Pattern

Middleware Order Rule

The order in backend/src/index.ts must follow:

security → cors → sanitization → rateLimiter → routes

Changing order can break security guarantees. See Middleware Stack for rationale.

Auth Middleware

Two authentication strategies:

StrategyMiddlewareToken TypeUsed By
Sessionauth.tsJWT (httpOnly cookie)Main app routes
Portalportal-auth.tsPortal token (URL param)Portal routes
Appointmentappointment-portal-auth.tsAppointment tokenAppointments portal

Rate Limiting

Endpoint GroupLimitWindow
Auth routes (/api/auth/*)5 requests15 minutes
General API100 requests1 minute

Backed by Upstash Redis. See Backend Architecture for Redis infrastructure.

Error Handler

errorHandler.ts catches all unhandled errors and:

  1. Logs the error with request context
  2. Reports to Sentry (with sensitive data scrubbing)
  3. Returns a structured JSON error response

See Error Handling Pattern for error response format.

Sanitization

sanitization.ts runs DOMPurify on all request body fields. Three sanitization levels:

LevelAllowed TagsUse Case
STRICTNone (strips all HTML)99% of user input
BASIC_FORMATTING<b>, <i>, <em>, <strong>, <br>Rich text fields
RICH_TEXTExtended setAdmin-only, never user input