Selegic CRM Docs
ServerMiddleware & Lifecycle

Architecture

Execution order, HandlerContext, and observability patterns.

Execution Order

Middleware is attached in routes/index.ts with a fixed order:

HTTP Request Resolve session from cookies Attach user/session Resolve org & attach TenantPrisma Pass context Verify authenticated Run before hooks Execute handler Response Run after hooks JSON Response Client sessionMiddleware tenantMiddleware requireAuth lifecycleMiddleware Route Handler

Order

  1. sessionMiddleware — Resolve user session from cookies/headers
  2. tenantMiddleware — Resolve org and attach TenantPrisma
  3. requireAuth — Ensure authenticated requests
  4. lifecycleMiddleware — Run before/after lifecycle hooks

HandlerContext

Middleware composes the HandlerContext used by services:

interface HandlerContext {
  // Request
  requestId: string;
  path: string;
  method: string;
  
  // Auth
  user: User | null;
  session: Session | null;
  
  // Tenant
  org: string;
  prisma: TenantPrisma;
}

Context Access in Handlers

app.get("/api/resource", requireAuth, async (c) => {
  const { user, org, prisma } = c.get("context");
  // Use context for DB operations
});

Observability

  • Add structured logs with requestId, org, userId
  • Include timing metadata
  • Log before throwing errors

Safety

  • Fail-fast: Throw HTTP errors immediately to prevent partial state
  • Avoid sync work: Move expensive operations to background
  • Idempotent: Ensure middleware can run multiple times safely

On this page