Backend Request Flow
Compass backend code follows a consistent route -> controller -> service pattern with middleware-heavy request setup.
Startup And Route Registration
Primary files:
packages/backend/src/app.tspackages/backend/src/servers/express/express.server.ts
Express startup does this:
- initialize SuperTokens
- install request middleware
- install CORS and SuperTokens middleware
- install helmet, logging, and JSON parsing
- register route config classes (including unauthenticated health check route)
- install the SuperTokens error handler after routes
Route Config Pattern
Each feature owns a *routes.config.ts file that extends CommonRoutesConfig.
Base class:
packages/backend/src/common/common.routes.config.ts
Typical ownership split:
- routes config: express path and middleware composition
- controller: request parsing and response orchestration
- service: business logic
- query/repo layer: database-specific access
Middleware Order Matters
The backend relies on middleware ordering for correct behavior:
- request/response promise helpers are installed before routes
- session middleware runs before route handlers that require auth
- SuperTokens error handling runs after routes
If a new route behaves strangely, verify it is registered inside initExpressServer() and uses the expected middleware stack.
Health Check Endpoint Pattern
Files:
packages/backend/src/health/health.routes.config.tspackages/backend/src/health/controllers/health.controller.ts
GET /api/health is registered as a lightweight operational endpoint:
- no
verifySession()requirement - controller performs
mongoService.db.admin().ping() - response contract is intentionally small:
{ status, timestamp } - returns
200(status: "ok") on successful DB ping,500(status: "error") on failure
This route is suitable for uptime probes and quick backend triage, but it is not a deep dependency readiness check beyond database reachability.
Response Pattern
File:
packages/backend/src/common/middleware/promise.middleware.ts
The backend decorates res with res.promise(...) so controllers can pass:
- a Promise
- a sync function
- a resolved value
Errors funnel through shared Express error handling.
Important response convention:
- controllers can return
{ statusCode: 204 }to emit a true empty204 No Contentresponse - this is handled centrally in
promise.middleware.ts(status-only payload special case) - avoids duplicating
res.status(...).send()patterns in controllers
Event Request Example
Files:
packages/backend/src/event/event.routes.config.tspackages/backend/src/event/controllers/event.controller.tspackages/backend/src/event/services/event.service.ts
For POST /api/event:
- route requires
verifySession() - controller adds the authenticated user id
- controller normalizes single vs array payloads
- controller forwards the change set to
CompassToGoogleEventPropagation - controller returns a status-only payload (
{ statusCode: 204 }) throughres.promise(...) - Compass-to-Google event propagation:
- loads current Compass DB state
- analyzes the transition into a persistence plan
- applies Compass DB mutations first
- executes any Google side effect implied by the transition
- if Google is not connected (
MissingGoogleRefreshToken), keeps the Compass mutation and skips the Google side effect - notifies clients after commit
PUT /api/event/:id and DELETE /api/event/:id follow the same write pattern:
- route-level auth guard (
verifySession()) without route-level Google-connection middleware - thin controller shaping into
CompassEvent res.promise(...)-based response and centralized error routing
This allows password-authenticated users to mutate Compass events even when no Google connection is present.
Common Auth Guards
Frequently used middleware:
verifySession(): authenticated Compass session requiredrequireGoogleConnectionSession: active Google connection required for routes that call Google directly (for example/api/sync/import-gcal)authMiddleware.verifyIsDev: development-only routeauthMiddleware.verifyIsFromCompass: trusted internal callerpublicWatchNotificationIngress.verify: trusted Google notification sourcepackages/backend/src/sync/services/public-watch-notifications/public-watch-notification.ingress.ts: Public watch notification header validation and payload parsing
Intentional unauthenticated route:
GET /api/health: monitoring endpoint that checks DB connectivity
Validation Placement
Validation is spread across a few layers:
- env validation at startup through Zod
- shared data schemas in
packages/core/src/types - query validation in feature utilities where needed
- controller/service parsing for request-specific inputs
When adding a public contract, prefer creating or extending a shared schema in core first.
How To Add A Backend Endpoint
- Add or reuse a shared schema/type in
coreif the contract is cross-package. - Register the route in the relevant
*routes.config.ts. - Keep the controller thin: extract params, user id, and response orchestration only.
- Put business logic in a service.
- Add or update tests at the controller/service level.
- If the endpoint affects realtime UI, check whether an SSE notification is also needed.
Where Bugs Usually Hide
- middleware ordering
- session requirement mismatches
- user id injection in controllers
- recurring event scope handling
- Mongo/ObjectId conversion around event ids
- returning instance events without rehydrating recurrence rules