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

15 KiB

type, title, description, tags, timestamp
type title description tags timestamp
architecture Key Files Index One-line responsibility for important source and contract-test files, including strict event-window validation, the public bootstrap SSE listener, the challenges full-replace import flow, the authenticated player-facing challenges board, and the per-user `solvedByMe` reset on the session boundary.
architecture
key-files
event-window
validation
default-challenge-ip
sse
bootstrap
migrations
challenges
import
board
notifications
per-user
session
2026-07-23T03:45:00Z

Backend

File Responsibility
backend/src/main.ts Bootstraps Nest, middleware, OpenAPI, static assets, and SPA fallback.
backend/src/app.module.ts Wires feature modules and global providers.
backend/src/config/env.schema.ts Zod-validated runtime config; canonical defaults for DATABASE_PATH (./data/db.sqlite) and UPLOAD_DIR (./data/uploads).
backend/src/database/database.module.ts Configures TypeORM with SQLite.
backend/src/database/database-init.service.ts Initializes the database and runs migrations; verifySeed() also asserts the canonical six system-category keys and reports missing/duplicate rows.
backend/src/database/migrations/1700000000400-RepairCategorySchemaAndSystemCategories.ts Forward-only repair migration: adds created_at/updated_at to legacy six-column category tables, deletes obsolete FOR/OSI system rows, rewrites canonical row metadata, inserts any missing canonical key, and re-asserts unique indexes. Exports CANONICAL_SYSTEM_CATEGORIES.
backend/src/common/guards/jwt-auth.guard.ts Global JWT authorization guard.
backend/src/common/middleware/csrf.middleware.ts Double-submit CSRF protection.
backend/src/common/services/event-status.service.ts Computes the event-window state machine.
backend/src/common/services/sse-hub.service.ts In-process pub/sub for server-sent event streams.
backend/src/modules/system/system.controller.ts Registers bootstrap, event status, settings, and SSE endpoints.
backend/src/modules/system/system.service.ts Builds the public bootstrap payload from admin existence, settings, the theme loader, and password-policy configuration.
backend/src/modules/admin/admin-general.controller.ts Registers admin general-settings and available-theme endpoints.
backend/src/modules/admin/general.service.ts Reads/writes global settings, filters available theme files, and publishes the general SSE notification after updates.
backend/src/modules/auth/auth.controller.ts Registers authentication and account endpoints.
backend/src/modules/auth/auth.service.ts Handles sessions, authentication, registration, and password changes.
backend/src/modules/uploads/uploads.controller.ts Registers admin-only multipart uploads, including Sharp-backed site-logo format validation and strict category-icon decode (rejects undecodable / non-image buffers with HTTP 400 before any filesystem write so existing icons are preserved).
backend/src/modules/admin/dto/general.dto.ts Zod contract for PUT /api/v1/admin/general/settings; both event timestamps are required ISO-8601 values and end must be strictly after start.
tests/backend/admin-general-event-window.spec.ts Focused contract tests for valid, empty, malformed, equal, and reversed event-window timestamps.
tests/backend/admin-general-service.spec.ts General-settings schema and service tests, including per-field empty datetime failures and settings-event emission.
tests/backend/admin-challenges-import-replace.spec.ts Contract tests for the confirmed-import full-replace: wipes unrelated pre-existing challenges, unlinks wiped disk files, empty archive, unknown-category skip-then-wipe.
backend/src/modules/challenges/challenges.module.ts Wires ChallengesController, ChallengesEventsController, ChallengesService, and the four TypeORM entities (ChallengeEntity, CategoryEntity, SolveEntity, UserEntity).
backend/src/modules/challenges/challenges.controller.ts Registers /api/v1/challenges/{board,status,:id,:id/solves} (all JWT-protected).
backend/src/modules/challenges/events.controller.ts Authenticated SSE /api/v1/events merging status ticks + hub general pushes + scoreboard$ solve frames.
backend/src/modules/challenges/challenges.service.ts getBoard / getDetail / submitFlag + dataSource.transaction for race-safe idempotent solves; publishes solve SSE frames on success.
backend/src/modules/challenges/dto/challenges.dto.ts zod contracts (SolveSubmitBodySchema, BoardQuerySchema, ChallengeIdParamSchema) + DTO types for the player-facing board.
backend/src/modules/challenges/scoring.util.ts Pure computeLivePoints, rankBonusForPosition, compareDifficulty, and constant-time safeEqualString for flag comparison.
backend/src/common/errors/error-codes.ts Canonical error code map (now includes EVENT_NOT_RUNNING, FLAG_INCORRECT, CHALLENGE_DISABLED).

Frontend

File Responsibility
frontend/src/main.ts Bootstraps Angular and registers HTTP interceptors.
frontend/proxy.conf.json Angular dev-server proxy: forwards /api and /uploads to http://localhost:3000.
frontend/angular.json Angular workspace config; the serve target references proxy.conf.json.
package.json (root) Root npm scripts; dev runs both workspaces via concurrently, dev:backend / dev:frontend run one at a time.
setup.sh Idempotent setup: installs root + workspace deps, builds both packages, creates ./data/uploads.
frontend/src/app/app.routes.ts Defines public, shell, child, and admin routes.
frontend/src/app/core/services/bootstrap.service.ts Caches and exposes bootstrap state, refreshes it after admin updates, and applies the resolved theme.
frontend/src/app/core/services/bootstrap.types.ts Defines bootstrap/theme payload types and maps theme tokens to CSS custom properties.
frontend/src/app/core/services/admin.service.ts Calls admin settings, theme-list, category, and upload APIs.
frontend/src/app/features/home/home.component.ts Authenticated shell container; starts user and event state services; on logout and on session invalidation also calls challengesStore.reset() to flush any per-user board cache before navigating to /login.
frontend/src/app/core/services/auth.service.ts Signal-backed access token and current-user state; owns the cross-tab invalidation BroadcastChannel + storage-event fallback.
frontend/src/app/core/services/auth-session-events.pure.ts Pure cross-tab message encoding/validation and namespaced constants used by the auth broadcast channel.
frontend/src/app/core/services/authenticated-event-source.service.ts Fetch-based authenticated SSE transport with frame parsing, abort support, and a separate 'unauthorized' event for 401/403.
frontend/src/app/core/services/bootstrap-event.service.ts Root-provided public SSE listener that subscribes to /api/v1/event/stream, filters topic === 'general' frames, and triggers BootstrapService.refresh() so the landing modal stays in sync with admin general-settings updates.
frontend/src/app/core/services/bootstrap-event.pure.ts Pure helpers for the public bootstrap SSE listener: isBootstrapGeneralFrame predicate, SSE line parser, and the makeBootstrapEventSource factory (fetch + ReadableStream opener with frame buffering and idempotent close()).
frontend/src/app/core/services/event-status.store.ts Event state signal store, one-second countdown timer, and the optional onUnauthorized callback wiring; exposes start()/stop()/closeTransport() for transport lifecycle and subscribeReloadAtCountdownZero(handler) (with reloadAtCountdownZero(handler) kept as a back-compat wrapper) so the reload handler is owned by its subscriber rather than the transport.
frontend/src/app/core/services/event-status.pure.ts Event payload types, transport interface (including 'unauthorized' listener), pure countdown helpers (formatDdHhMm returns DD:HH:mm:ss and deriveCountdownText), and the LED_COLOR_BY_STATE map used by the shell LED.
frontend/src/app/features/home/home.component.ts Authenticated shell container; starts user and event state services, subscribes to peer invalidation, resets both UserStore and ChallengesStore, and navigates to /login when the session is invalidated elsewhere.
frontend/src/app/features/shell/header/shell-header.component.ts Shell title, status LED (size/shape only — color comes from the pure map via [style.background-color]), countdown, and user menu.
frontend/src/app/features/shell/tabs/quick-tabs.component.ts Main shell navigation tabs.
frontend/src/app/features/shell/change-password/change-password-modal.component.ts Change-password form modal.
frontend/src/app/features/admin/general.component.ts AdminGeneralComponent reactive form for /admin/general — per-field inline error rendering (page-title + event-start + event-end), logo upload wiring, welcome Markdown preview, event-state derivation, and SSE general event handling.
frontend/src/app/features/admin/categories/category-form-modal.component.ts Standalone OnPush modal for create + edit; owns the CategoryFormGroup, exposes the pure syncCategoryForm helper, binds [formGroup] on its template <form>, accepts errorMessage + saving parent inputs (renders cf-error and disables OK while saving), and reacts to open / mode / category signal inputs via a markForCheck effect so edit prefill reaches the DOM.
frontend/src/app/features/admin/general.pure.ts Pure General Settings helpers, including required datetime validation, field messages, UTC conversion, end-after-start validation, and the default-challenge-address IPv4/hostname validator/normalizer/message trio.
tests/frontend/admin-general-pure.spec.ts Pure client-contract tests for required event timestamps, datetime messaging, UTC conversion, event-window ordering, and default-challenge-address validation, error mapping, and normalization.
tests/frontend/admin-categories-form-modal.spec.ts Tests the pure syncCategoryForm helper that drives the edit/create prefill in CategoryFormModalComponent: system-row abbreviation lock, user-row unlock, re-population on second invocation, clearing on create, and iconPreview passthrough.
tests/frontend/authenticated-event-source.spec.ts Tests SSE authorization, frame transport behavior, and the 401/403 unauthorized path.
tests/frontend/auth-session-events.spec.ts Pure tests for cross-tab invalidation message encoding, payload validation, and storage-event filtering.
tests/frontend/admin-challenges-import-autoclose.spec.ts Pure helpers (summarizeImportResult, importErrorMessage) and modal auto-close branch for the confirmed-import handler.
frontend/src/app/features/challenges/challenges.page.ts /challenges smart page: gate logic (countdown/running/stopped/unconfigured), modal lifecycle, SSE wiring on /api/v1/events, and the page-owned countdown-zero reload (handler registered in the constructor with the disposer wired into DestroyRef).
frontend/src/app/features/challenges/challenges.store.ts Signal store: board, event state, per-card solve listeners, SSE solve-frame mutation, submit response application, stop() lifecycle, public reset() for the session-boundary flush, and setMyUserId(id) which now returns the previous id and clears the cache whenever the cached state belongs to an unknown or different user.
frontend/src/app/features/challenges/challenges.service.ts HTTP service for /api/v1/challenges/{board,status,:id,:id/solves} returning typed ApiErrorEnvelopes. getDetail always requests ?include=solvers so the modal can render the solvers list in one round-trip; getBoard only attaches include=solvers when the caller opts in.
frontend/src/app/features/challenges/challenges.pure.ts Pure types and helpers (BoardCard, SolverRow, SolveEventPayload, parseSolveEvent, mergeSolveEventIntoSolvers, messageForSolveError, formatDdHhMm).
frontend/src/app/features/challenges/category-column.component.ts Renders a single category column (header + cards) on the challenges board.
frontend/src/app/features/challenges/challenge-card.component.ts Renders a single challenge card on the board (difficulty, live points, solve count, when solved by the player).
frontend/src/app/features/challenges/challenge-modal.component.ts Challenge detail modal: description, flag form, awarded banner, solvers list, live-solve updates.
frontend/src/app/core/services/notification.service.ts Root-provided signal-backed store of { id, kind, message, ts } records; error() / info() push, dismiss(id) / clear() remove.
frontend/src/app/core/interceptors/error-notification.interceptor.ts Translates HttpErrorResponse into friendly messages and pushes them to NotificationService (with suppression for /api/v1/auth/{login,csrf,register} and /api/v1/challenges/status).
tests/frontend/challenges.pure.spec.ts Pure helpers: sorting, parsers, friendly error mapping, formatDdHhMm (DD:HH:mm:ss).
tests/frontend/challenges.service.spec.ts HTTP-service contract: getDetail URL-encodes the id, attaches ?include=solvers, and forwards withCredentials: true.
tests/frontend/challenges.store.spec.ts Signal store: board mutation, live solve merge, listeners, stop(). The "marks solvedByMe" and "does not double-count" tests now call setMyUserId('me-1') before load() to exercise the realistic page-mount sequence.
tests/frontend/challenges.store.reset.spec.ts Per-user solvedByMe regression suite: reset() clears board/detail/myUserId/SSE; switching user id flushes the previous board; orphan board (cached with no recorded user id) is cleared when PlayerB's id is set; a non-mine solve never flips solvedByMe from false to true; applySubmitResponse takes the server value verbatim.
tests/frontend/notification-interceptor.spec.ts Interceptor suppression rules and friendly message mapping.
tests/backend/challenges-board.spec.ts Board query shape, ordering, ?include=solvers.
tests/backend/challenges-status-rest.spec.ts /api/v1/challenges/status snapshot shape.
tests/backend/challenges-events-sse.spec.ts /api/v1/events SSE: status + solve frames, dedup, ordering.
tests/backend/challenges-submit-flag.spec.ts Submit flow: correct/incorrect flag, idempotent re-submit, event-state guard, race handling.

See also