Skip to main content

Backend Overview

The Qlarr backend is a NestJS application providing REST APIs for survey management, execution, and data synchronization. It lives in the backend/ directory of the Qlarr monorepo.

Repository

qlarr-surveys/qlarr — the backend is the backend/ folder of the monorepo (alongside frontend/ and deploy/).

Role in the System

The backend is the central hub of the Qlarr ecosystem. It binds the same @qlarr/survey-engine build the web and Android renderers use, and exposes its capabilities via REST APIs. The Frontend communicates with it for both survey design and execution, and the Android app connects to it to download surveys and sync responses.

It is single-tenant: one database, one organization, with an admin seeded on first run.

Technology Stack

  • NestJS 10 with TypeScript (Node.js 20+)
  • TypeORM over PostgreSQL — survey settings, responses, user data (synchronize: false; an in-process baseline migration owns the schema)
  • @qlarr/survey-engine — the JavaScript build of the Survey Engine, run on Piscina worker threads so a runaway survey design can be timed out and killed without blocking the server
  • Passport JWT — stateless authentication (access + refresh tokens)
  • Local-disk file storage (LocalFileHelper) — survey resources, designs, and response files under {FILE_SYSTEM_ROOT_FOLDER}/{surveyId}/{folder}/{file}; the FileHelper interface is the swap seam for other backends (e.g. object storage)
  • nodemailer — outbound email (leave MAIL_HOST empty to log instead of send)

Authentication

The backend uses stateless JWT-based authentication with refresh tokens.

Token Types

TokenExpirationPurpose
Access token1 hourSent in the Authorization: Bearer {token} header for API requests
Refresh token1 yearStored in the database, used to obtain a new access token
Password reset token1 hour (30 days for new users)Sent via email for password reset flow

Expirations are configurable via JWT_ACTIVE_EXPIRATION_MS, JWT_REFRESH_EXPIRATION_MS, JWT_RESET_EXPIRATION_MS, and JWT_RESET_EXPIRATION_NEW_USERS_MS. Tokens are signed with HS256 (HMAC SHA-256) using the base64-decoded JWT_SECRET. The token contains the user email (sub), user ID, roles (authorities), and session ID as claims.

Auth Flow

  1. User logs in with email and password (POST /user/login)
  2. Backend validates credentials (bcrypt) and returns an access token + refresh token
  3. Client includes the access token in the Authorization: Bearer {token} header for subsequent requests
  4. When the access token expires, the client uses the refresh token to get a new one (POST /user/refresh_token) — refresh tokens are not rotated
  5. Logout (POST /logout) invalidates the current session

Roles

  • Super Admin — full system access, user management
  • Survey Admin — survey management
  • Surveyor — create and run surveys
  • Analyst — analyze survey responses

Public Endpoints

The following endpoints do not require authentication:

  • Survey execution (/survey/{surveyId}/run/*)
  • Survey resources and attachments
  • Login, password reset, and token refresh

A global JwtAuthGuard protects every route by default; the @Public() decorator opts a route out. Role-based access is enforced by a RolesGuard reading @Roles(...) metadata. Sensitive routes (login, forgot/confirm password) are additionally rate-limited.

API Endpoints

See the API Reference for the complete list of endpoints.