Files
HIPCTF2/docs/architecture/backend-modules.md
T

12 KiB

type, title, description, tags, timestamp
type title description tags timestamp
architecture Backend Module Map NestJS modules, controllers, services, and how they are wired together.
architecture
backend
nestjs
modules
2026-07-23T16:10:00Z

Module Map

All modules are imported in backend/src/app.module.ts. The root module also registers two global providers:

Global provider Purpose
APP_GUARD = JwtAuthGuard Enforces JWT auth unless the handler is @Public()
APP_FILTER = GlobalExceptionFilter Normalizes errors into the standard envelope

Modules

Module Path Responsibility
DatabaseModule backend/src/database/database.module.ts Configures TypeORM with better-sqlite3, registers entities, runs migrations, enforces WAL, and imports FilesystemTransactionModule so startup recovery runs before the database is opened.
FilesystemTransactionModule backend/src/modules/admin/system/filesystem-transaction.module.ts Provides the shared durable filesystem swap service to both DatabaseModule startup recovery and AdminSystemModule restore operations without a circular dependency.
CommonModule backend/src/common/common.module.ts Provides shared services (CSRF middleware class, backoff, registration rate limit, SSE hub, theme loader, etc.).
SettingsModule backend/src/modules/settings/settings.module.ts Exposes SettingsService (get/set/getAll over setting table).
AuthModule backend/src/modules/auth/auth.module.ts AuthController (/api/v1/auth/{register,login,refresh,logout,me,change-password,csrf}) + AuthService (login/refresh/logout/register-first-admin + public register + getMe + changePassword). Imports SettingsModule so the public-register flow can read the registrationsEnabled flag, and UsersModule (forwardRef) for UsersRankService.
UsersModule backend/src/modules/users/users.module.ts UsersController (/api/v1/auth/register-first-admin) + UsersService (last-admin invariant) + UsersRankService (rankOfUser(manager, userId) -> {rank, points} over the solve table).
SetupModule backend/src/modules/setup/setup.module.ts SetupController (POST /api/v1/setup/create-admin) + SetupService. Returns 409 SYSTEM_INITIALIZED once any admin exists; serializes concurrent first-admin attempts via an in-process promise chain.
SystemModule backend/src/modules/system/system.module.ts SystemController (/api/v1/bootstrap, /event/status, SSE streams) + SystemService.
AdminModule backend/src/modules/admin/admin.module.ts Five controllers (AdminController for /api/v1/admin/users*, AdminGeneralController for /api/v1/admin/general/*, AdminCategoriesController for /api/v1/admin/categories*, AdminChallengesController for /api/v1/admin/challenges*, AdminSystemController for /api/v1/admin/system/*) plus their services (AdminService, AdminGeneralService, AdminCategoriesService, AdminChallengesService, ChallengeFilesService, BackupService, RestoreService, DangerZoneService, FilesystemTransactionService, ConfirmationTokenService). Gated by AdminGuard + @Roles('admin'). Imports TypeOrmModule.forFeature([UserEntity, CategoryEntity, ChallengeEntity, ChallengeFileEntity, SolveEntity]), AuthModule, UsersModule, SettingsModule, CommonModule (for SseHubService, ThemeLoaderService), and AdminSystemModule (which adds AdminOperationTokenEntity + AuthModule).
AdminSystemModule backend/src/modules/admin/system/admin-system.module.ts Hosts the destructive System operations: AdminSystemController + BackupService + RestoreService + DangerZoneService + ConfirmationTokenService. Imports shared FilesystemTransactionModule, TypeOrmModule.forFeature([AdminOperationTokenEntity]), and AuthModule (for reauthenticateAdmin/revokeAllRefreshSessions).
UploadsModule backend/src/modules/uploads/uploads.module.ts UploadsController (/api/v1/uploads/*). Admin-only multipart.
BlogModule backend/src/modules/blog/blog.module.ts BlogController/BlogService expose published posts at GET /api/v1/blog/posts; AdminBlogController/AdminBlogService provide guarded CRUD at /api/v1/admin/blog/posts using BlogPostEntity.
ChallengesModule backend/src/modules/challenges/challenges.module.ts ChallengesController (/api/v1/challenges/{board,status,:id,:id/solves}) + ChallengesEventsController (authenticated SSE /api/v1/events) + ChallengesService (board, detail, submit, scoring util).
FrontendModule backend/src/frontend/frontend.module.ts Registers SpaFallbackMiddleware and the uploads static helper.

Controllers

Controller Path prefix Auth Source
AuthController /api/v1/auth Mostly public (login, refresh, logout, csrf) backend/src/modules/auth/auth.controller.ts
UsersController /api/v1/auth/register-first-admin Public (bootstrap-only) backend/src/modules/users/users.controller.ts
SetupController /api/v1/setup/create-admin Public (bootstrap-only; 409 SYSTEM_INITIALIZED once an admin exists) backend/src/modules/setup/setup.controller.ts
AdminController /api/v1/admin Admin only backend/src/modules/admin/admin.controller.ts
AdminGeneralController /api/v1/admin/general Admin only backend/src/modules/admin/admin-general.controller.ts
AdminCategoriesController /api/v1/admin/categories Admin only backend/src/modules/admin/admin-categories.controller.ts
AdminChallengesController /api/v1/admin/challenges Admin only backend/src/modules/admin/admin-challenges.controller.ts
AdminSystemController /api/v1/admin/system Admin only (plus confirmation tokens for destructive ops) backend/src/modules/admin/system/admin-system.controller.ts
SystemController /api/v1 Mixed (bootstrap/event/scoreboard/settings are public; events/status SSE is JWT-protected) backend/src/modules/system/system.controller.ts
UploadsController /api/v1/uploads Admin only backend/src/modules/uploads/uploads.controller.ts
BlogController /api/v1/blog Public backend/src/modules/blog/blog.controller.ts
AdminBlogController /api/v1/admin/blog/posts Admin only backend/src/modules/blog/admin-blog.controller.ts
ChallengesController /api/v1/challenges Authenticated backend/src/modules/challenges/challenges.controller.ts
ChallengesEventsController /api/v1/events Authenticated (SSE) backend/src/modules/challenges/events.controller.ts

Common services

Service Path Purpose
CsrfMiddleware backend/src/common/middleware/csrf.middleware.ts Mints/validates CSRF tokens via cookie + header.
JwtAuthGuard backend/src/common/guards/jwt-auth.guard.ts Global guard; honors @Public() decorator.
AdminGuard backend/src/common/guards/admin.guard.ts Requires authenticated user with role === 'admin'.
RolesGuard backend/src/common/guards/roles.guard.ts Enforces @Roles(...) metadata.
GlobalExceptionFilter backend/src/common/filters/global-exception.filter.ts Converts exceptions to standard envelope.
EventStatusService backend/src/common/services/event-status.service.ts Computes the 4-state event state machine (countdown/running/stopped/unconfigured) via getState() plus the legacy getStatus() shape (Stopped/Running + countdownMs).
LoginBackoffService backend/src/common/services/login-backoff.service.ts Per-IP+username brute-force throttle.
RegistrationRateLimitService backend/src/common/services/registration-rate-limit.service.ts Per-IP rate limit on first-admin registration.
SseHubService backend/src/common/services/sse-hub.service.ts In-process pub/sub for SSE streams.
ThemeLoaderService backend/src/common/utils/theme-loader.service.ts Loads + validates the 10 canonical themes.
ZodValidationPipe backend/src/common/pipes/zod-validation.pipe.ts Replaces ValidationPipe for zod-validated DTOs.
TransformInterceptor backend/src/common/interceptors/transform.interceptor.ts Optional response transformer.
scoring.util backend/src/modules/challenges/scoring.util.ts computeLivePoints, rankBonusForPosition, compareDifficulty, and safeEqualString (constant-time flag compare).

Decorators

Decorator Path Purpose
@Public() backend/src/common/decorators/public.decorator.ts Mark a route as unauthenticated.
@Roles(...) backend/src/common/decorators/roles.decorator.ts Required role(s).
@SkipCsrf() backend/src/common/decorators/skip-csrf.decorator.ts Exempt a route from CSRF check.

Startup chain

main.tsAppModule (loads ConfigModule, then all feature modules) → DatabaseInitService.init()FilesystemTransactionService.recoverTransactions() (resolves interrupted restore manifests before TypeORM opens the live SQLite file; ambiguous generations abort startup) → stale unowned swap-artifact sweep → migrations + WAL → verifySeed() (best-effort) → ensureSystemCategoryIcons() (best-effort — writes CRY/HW/MSC/PWN/REV/WEB.png into <UPLOAD_DIR>/icons/ if missing so freshly bootstrapped instances never serve 404 icons; see System Category Icon Seed) → app.use(...) middlewares (helmet, parsers, CSRF, static) → SwaggerModule.setup(...) (OpenAPI 3.1) → SpaFallbackMiddlewareapp.listen().

See also