Files
HIPCTF2/docs/architecture/key-files.md
T

25 KiB

type, title, description, tags, timestamp
type title description tags timestamp
architecture Key Files Index One-line responsibility for every important source file in the repository.
architecture
index
key-files
2026-07-21T22:19:08Z

Backend

Entrypoint & config

File Responsibility
backend/src/main.ts Bootstraps Nest, registers middleware, builds OpenAPI 3.1, mounts SPA fallback.
backend/src/app.module.ts Root module; wires every feature module + global guards/filters.
backend/src/config/env.schema.ts Zod-validated env schema, SETTINGS_KEYS, system category metadata.

Database

File Responsibility
backend/src/database/database.module.ts TypeORM better-sqlite3 config, entity + migration registration.
backend/src/database/database-init.service.ts Initializes the DataSource, enforces WAL PRAGMA, runs migrations, verifies seed.
backend/src/database/migrations/1700000000000-InitSchema.ts Creates all tables and sets WAL + foreign keys.
backend/src/database/migrations/1700000000100-SeedSystemData.ts Seeds the 6 system categories and default settings.
backend/src/database/entities/user.entity.ts user table (admin/player role, enabled/disabled status).
backend/src/database/entities/setting.entity.ts setting table.
backend/src/database/entities/category.entity.ts category table with system_key unique index.
backend/src/database/entities/challenge.entity.ts challenge table (difficulty, decay, protocol, flag, port).
backend/src/database/entities/challenge-file.entity.ts challenge_file table for attachments.
backend/src/database/entities/solve.entity.ts solve table with unique (challenge_id, user_id) (used by UsersRankService).
backend/src/database/entities/refresh-token.entity.ts refresh_token table (token_hash + revocation).
backend/src/database/entities/blog-post.entity.ts blog_post table (draft/published + publishedAt index).

Common

File Responsibility
backend/src/common/common.module.ts Aggregates common services, middleware, and providers.
backend/src/common/middleware/csrf.middleware.ts Double-submit CSRF check; mints/reads cookie, compares header.
backend/src/common/guards/jwt-auth.guard.ts Global JWT guard; honors @Public().
backend/src/common/guards/admin.guard.ts Requires req.user.role === 'admin'.
backend/src/common/guards/roles.guard.ts Enforces @Roles(...) metadata.
backend/src/common/decorators/public.decorator.ts @Public() marker.
backend/src/common/decorators/roles.decorator.ts @Roles(...) metadata.
backend/src/common/decorators/skip-csrf.decorator.ts @SkipCsrf() marker.
backend/src/common/filters/global-exception.filter.ts Converts all errors to the standard envelope.
backend/src/common/pipes/zod-validation.pipe.ts Validates body/param/query with a zod schema.
backend/src/common/interceptors/transform.interceptor.ts Optional response transformer.
backend/src/common/services/event-status.service.ts 4-state machine (countdown/running/stopped/unconfigured) via getState(); legacy getStatus() shape preserved for backward compatibility.
backend/src/common/services/login-backoff.service.ts Per-IP+username failed-login throttle.
backend/src/common/services/registration-rate-limit.service.ts Per-IP first-admin registration throttle.
backend/src/common/services/sse-hub.service.ts In-process pub/sub for event status and scoreboard streams.
backend/src/common/utils/openapi31.ts Converts the Nest-generated OpenAPI 3.0 doc to OpenAPI 3.1.
backend/src/common/utils/password-policy.ts Argon2 password validator (length, mixed-case policy).
backend/src/common/utils/theme-loader.service.ts Loads themes from disk, backfills built-ins, validates tokens.
backend/src/common/utils/upload.ts Upload size-limit parser + filename sanitizer.
backend/src/common/types/theme.ts, theme-ids.ts Theme interface and the 10 canonical ThemeIds.
backend/src/common/errors/api-error.ts ApiError class (status + machine code + message + details).
backend/src/common/errors/error-codes.ts Canonical ERROR_CODES enum (now includes INVALID_OLD_PASSWORD, PASSWORD_POLICY, PASSWORDS_DO_NOT_MATCH).

Modules

File Responsibility
backend/src/modules/auth/auth.module.ts Wires AuthController, AuthService, JwtStrategy; imports SettingsModule for the public register flow and UsersModule (forwardRef) for UsersRankService.
backend/src/modules/auth/auth.controller.ts /api/v1/auth/{register,login,refresh,logout,csrf,me,change-password}. logout, me, and change-password are JWT-protected (CSRF-enforced on change-password).
backend/src/modules/auth/auth.service.ts Login, refresh, logout, register-first-admin, public player self-registration (registerPlayer), session minting, getMe(userId) (rank + points), changePassword(userId, dto) (revoke-all-refresh-tokens on success).
backend/src/modules/auth/cookie.ts setRefreshCookie / clearRefreshCookie helpers.
backend/src/modules/auth/dto/auth.dto.ts Zod schemas for login + refresh + RegisterDtoSchema + ChangePasswordDtoSchema + MeResponseDtoSchema.
backend/src/modules/auth/strategies/jwt.strategy.ts Passport JWT strategy.
backend/src/modules/users/users.module.ts Wires UsersController + UsersService + UsersRankService.
backend/src/modules/users/users-rank.service.ts Pure provider rankOfUser(manager, userId) returning {rank, points} by summing pointsAwarded from solve and counting distinct users ahead.
backend/src/modules/users/users.controller.ts /api/v1/auth/register-first-admin.
backend/src/modules/users/users.service.ts enforceLastAdminInvariant helper.
backend/src/modules/users/dto/create-first-admin.dto.ts Zod schema for first-admin registration.
backend/src/modules/setup/setup.module.ts Wires SetupController + SetupService (dedicated first-admin bootstrap flow).
backend/src/modules/setup/setup.controller.ts POST /api/v1/setup/create-admin (returns 404 once an admin exists).
backend/src/modules/setup/setup.service.ts Hashes password (Argon2id), runs the create inside a transaction, mints session via AuthService.createSession.
backend/src/modules/setup/dto/create-admin.dto.ts Zod schema with password === passwordConfirm refine.
backend/src/modules/admin/admin.module.ts Wires AdminController + AdminService.
backend/src/modules/admin/admin.controller.ts /api/v1/admin/users[/{id}].
backend/src/modules/admin/admin.service.ts list / create / update role / delete user with last-admin guard.
backend/src/modules/admin/dto/admin.dto.ts Zod schemas for admin endpoints.
backend/src/modules/system/system.module.ts Wires SystemController + SystemService + status + hub services.
backend/src/modules/system/system.controller.ts /api/v1/{bootstrap,event/status,event/stream,settings/event,scoreboard/stream} (public) + authenticated SSE /events/status (plural, JWT-protected).
backend/src/modules/system/system.service.ts Builds the public bootstrap payload from settings + theme + admin count + password policy.
backend/src/modules/uploads/uploads.module.ts Wires UploadsController.
backend/src/modules/uploads/uploads.controller.ts /api/v1/uploads/{category-icon,challenge-file}.
backend/src/modules/blog/blog.module.ts Wires BlogController + BlogService (registers BlogPostEntity).
backend/src/modules/blog/blog.controller.ts GET /api/v1/blog/posts (public).
backend/src/modules/blog/blog.service.ts listPublished() returns published posts ordered by publishedAt DESC.
backend/src/modules/blog/dto/blog.dto.ts Zod schemas PublicBlogPostSchema + PublicBlogListSchema.
backend/src/modules/settings/settings.module.ts SettingsService (get/set/getAll over the setting table).
backend/src/frontend/frontend.module.ts Wires SPA fallback + uploads static middleware.
backend/src/frontend/spa.controller.ts SpaFallbackMiddleware (returns index.html for client routes).
backend/src/frontend/uploads-static.middleware.ts Mounts /uploads static helper.

Themes

File Responsibility
backend/themes/01-classic.json classic theme tokens.
backend/themes/02-midnight.json10-monochrome.json The other 9 canonical themes.

Frontend

File Responsibility
frontend/src/main.ts Bootstraps the standalone Angular app + registers interceptors.
frontend/src/index.html Root HTML shell.
frontend/src/styles.css Global styles consuming theme CSS custom properties.
frontend/src/app/app.component.ts Root component; triggers bootstrap then AuthService.restoreSession() on init.
frontend/src/app/app.routes.ts Angular route table (bootstrap, login, shell / with child routes challenges/scoreboard/blog/admin, wildcard **).
frontend/src/app/core/services/auth.service.ts Signal store for access token + current user; persists to sessionStorage, exposes restoreSession(), waitUntilHydrated(), login(), register(), logout(), me(), changePassword() (all with ensureCsrf() + discriminated LoginResult/RegisterResult/ChangePasswordResult), setSession().
frontend/src/app/core/services/auth.session-storage.ts Pure sessionStorage helpers (readStoredSession, writeStoredSession, clearStoredSession) under key hipctf.auth.v1.
frontend/src/app/core/services/bootstrap.service.ts Fetches /api/v1/bootstrap, applies theme tokens to CSS; exposes a passwordPolicy computed signal derived from the bootstrap payload.
frontend/src/app/core/services/event-status.store.ts Signal store for the live event window (state, serverNowUtc, eventStartUtc, eventEndUtc, derived countdownText); start(createSource)/stop() manage the SSE connection + 1-second tick.
frontend/src/app/core/services/event-status.pure.ts Pure helpers used by the store and tests: deriveCountdownText, formatDdHhMm, EventSourceLike, EventState/EventStatePayload.
frontend/src/app/core/services/user.store.ts Signal store for the authenticated user (user, loading, error, derived rankText); hydrateFromAuth() + loadMe() (calls AuthService.me()).
frontend/src/app/core/services/admin.service.ts GET /api/v1/admin/users returning AdminUser[].
frontend/src/app/core/services/markdown.service.ts Thin Angular MarkdownService.render(md): string that forwards to renderMarkdownToHtml. The DOMPurify sanitization happens inside renderMarkdownToHtml so Angular's [innerHTML] binding receives a sanitized plain string — no DomSanitizer.bypassSecurityTrustHtml wrapper is required.
frontend/src/app/core/services/markdown.pure.ts Pure renderMarkdownToHtml helper using marked + DOMPurify (kept in its own file so it can be unit-tested without Angular's ESM-only runtime and so the sanitization boundary is shared between production and tests).
frontend/src/app/core/guards/auth.guard.ts Async CanActivateFn; awaits bootstrap + auth hydration, delegates to decideAuthRedirect.
frontend/src/app/core/guards/auth.guard.decision.ts Pure decision function for the auth guard (returns true or a redirect UrlTree).
frontend/src/app/core/guards/admin.guard.ts Async CanActivateFn for admin-only routes; awaits bootstrap + auth hydration, delegates to decideAdminGuard.
frontend/src/app/core/guards/admin.guard.decision.ts Pure decision function for the admin guard (returns allow / redirect).
frontend/src/app/core/guards/landing.guard.ts Async CanActivateFn for /login; awaits bootstrap + auth hydration, then delegates to the pure decideLandingGuard.
frontend/src/app/core/guards/landing.guard.decision.ts Pure decision: returns true to render the landing page, or UrlTree to /bootstrap (not initialized) or / (already authenticated).
frontend/src/app/core/interceptors/auth.interceptor.ts Attaches Bearer header.
frontend/src/app/core/interceptors/csrf.interceptor.ts Attaches X-CSRF-Token on unsafe methods.
frontend/src/app/features/landing/landing.component.{ts,html,css} Public landing page (logo, page title, rendered welcomeMarkdown, login button, blog list) + modal containing the login and registration forms (toggled by the same mode signal). The template binds the welcome card via [innerHTML]="welcomeHtml()" (the computed signal invoked); binding the raw welcomeHtml signal object would render the runtime helper source — see tests/frontend/landing-welcome.spec.ts.
frontend/src/app/features/landing/landing.service.ts Fetches GET /api/v1/blog/posts, exposes posts/loading/error signals, refresh().
frontend/src/app/features/landing/login-modal.service.ts Pure buildLoginFailureMessage helper that maps {code,message} into user-facing copy (handles INVALID_CREDENTIALS, RATE_LIMITED, CSRF_INVALID, USERNAME_TAKEN, WEAK_PASSWORD, REGISTRATIONS_DISABLED, VALIDATION_FAILED).
frontend/src/app/features/admin/admin-users.component.ts Admin-only user list (signals: loading, error, users).
frontend/src/app/features/setup/setup-create-admin.component.ts First-admin modal overlay (non-dismissible; typed reactive form).
frontend/src/app/features/setup/setup-create-admin.service.ts POSTs to /api/v1/setup/create-admin and tags the result with the error code.
frontend/src/app/features/setup/setup-create-admin.validators.ts Standalone passwordMatchValidator group-level reactive form validator.
frontend/src/app/features/setup/setup-create-admin.field-errors.ts Pure usernameError / passwordError / confirmError helpers that turn reactive-form state into the inline validation messages rendered next to each input.
frontend/src/app/features/home/home.component.ts Smart authenticated shell: renders ShellHeaderComponent, QuickTabsComponent, ChangePasswordModalComponent, and <router-outlet>. Owns the SSE lifecycle (EventStatusStore.start/stop), the UserStore.loadMe() call, and the open/close signals for the change-password modal.
frontend/src/app/features/home/home.shell.ts Pure shouldShowAdminNav({isAuthenticated, role}) and deriveActiveSectionFromUrl(url) predicates (unit-tested).
frontend/src/app/features/shell/header/shell-header.component.ts Dumb header: page title, active-section label, LED (led-{state} class), countdown text, user menu trigger, inline user menu dropdown with rank / change-password / admin / logout entries.
frontend/src/app/features/shell/tabs/quick-tabs.component.ts Dumb Challenges / Scoreboard / Blog tab strip; tabs/active inputs, tabChange output.
frontend/src/app/features/shell/change-password/change-password-modal.component.ts Dumb reactive-form modal (mode `'self'
frontend/src/app/features/shell/change-password/change-password-modal.validators.ts passwordMatchValidator group validator + PasswordPolicy zod schema.
frontend/src/app/features/shell/change-password/password-feedback.ts Pure formatChangePasswordError({code, message}) helper that maps the API code to user-facing copy.
frontend/src/app/features/challenges/challenges.page.ts Placeholder /challenges page.
frontend/src/app/features/scoreboard/scoreboard.page.ts Placeholder /scoreboard page.
frontend/src/app/features/blog/blog.page.ts Placeholder /blog page.

Tests

File Responsibility
tests/backend/*.spec.ts (~25 suites) Jest tests for backend modules, CSRF, OpenAPI 3.1, migrations, rate limits, the new /me + /change-password + authenticated SSE flows, and UsersRankService.
tests/frontend/theme.spec.ts Jest test for theme token application.
tests/frontend/admin-shell.spec.ts Unit tests for shouldShowAdminNav predicate.
tests/frontend/admin-navigation.spec.ts Tests for admin guard decision + nav-link rendering.
tests/frontend/auth-restore.spec.ts Round-trips auth.session-storage helpers + refresh success/failure paths.
tests/frontend/setup-create-admin.spec.ts Pure-Jest tests for passwordMatchValidator and the three field-error helpers (usernameError, passwordError, confirmError).
tests/frontend/guard-bootstrap-race.spec.ts Pins decideAuthRedirect so a refresh on a deep link never flashes /bootstrap or /login while auth is hydrating.
tests/frontend/landing-guard.spec.ts Pins decideLandingGuard for the not-initialized / authenticated / anonymous branches.
tests/frontend/landing-markdown.spec.ts Pins renderMarkdownToHtml (sanitization of raw <script> payloads, script URL schemes, etc.).
tests/frontend/landing-welcome.spec.ts Regression test for the landing welcome binding — asserts the bootstrap payload's welcomeMarkdown produces the expected sanitized HTML (h1 + paragraph) and never the Angular runtime helper source string, including for null/empty/hostile payloads.
tests/frontend/landing-modal.spec.ts Pins buildLoginFailureMessage (INVALID_CREDENTIALS, RATE_LIMITED with retry-seconds extraction, CSRF_INVALID, USERNAME_TAKEN, WEAK_PASSWORD, REGISTRATIONS_DISABLED, VALIDATION_FAILED, default fallback).
tests/frontend/event-status.store.spec.ts Pins EventStatusStore.applyServerStatus (state + delta anchor) and deriveCountdownText (countdown / running / stopped / unconfigured).
tests/frontend/change-password-modal.spec.ts Pins the dumb modal's reactive form (validation, submit/cancel emission, error rendering).
tests/frontend/shell-active-section.spec.ts Pins deriveActiveSectionFromUrl for the four URL branches.
tests/backend/change-password.spec.ts Integration coverage for /api/v1/auth/change-password (wrong-old / mismatched / weak / unauth branches).
tests/backend/event-status-state.spec.ts Pins the 4-state derivation in EventStatusService.getState().
tests/backend/events-status-sse.spec.ts Pins the authenticated SSE stream (401 + initial EventStatePayload).
tests/backend/me-endpoint.spec.ts Pins /api/v1/auth/me (401 + payload shape including rank/points).
tests/backend/rank-points.spec.ts Pure unit test for UsersRankService.rankOfUser().
tests/backend/auth-register.spec.ts Backend integration tests for POST /api/v1/auth/register (happy path, disabled flag, duplicate username, weak password, rate limit).
tests/backend/blog-public.spec.ts Backend integration tests for GET /api/v1/blog/posts (only published rows, descending order).
tests/backend/csrf-protected-routes.spec.ts Pins CSRF enforcement on the formerly-skipped /api/v1/auth/login route.
tests/backend/csrf-client.ts Test helper for CSRF flow.
tests/backend/db-helper.ts Test helper for spinning up an isolated DB.

See also