docs: update documentation to OKF v0.1 format

This commit is contained in:
OpenVelo Agent
2026-07-22 19:56:30 +00:00
parent 113dd47371
commit 3c146a92f9
6 changed files with 136 additions and 7 deletions
+5
View File
@@ -12,6 +12,7 @@ timestamp: 2026-07-22T19:18:00Z
|---|---| |---|---|
| `backend/src/main.ts` | Bootstraps Nest, middleware, OpenAPI, static assets, and SPA fallback. | | `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/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.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/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/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`. |
@@ -35,6 +36,10 @@ timestamp: 2026-07-22T19:18:00Z
| File | Responsibility | | File | Responsibility |
|---|---| |---|---|
| `frontend/src/main.ts` | Bootstraps Angular and registers HTTP interceptors. | | `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/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.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/bootstrap.types.ts` | Defines bootstrap/theme payload types and maps theme tokens to CSS custom properties. |
+3 -3
View File
@@ -27,12 +27,12 @@ Browser ──HTTPS──▶ NestJS process (PORT, default 3000)
├── /api/v1/* ── controllers → services → TypeORM ├── /api/v1/* ── controllers → services → TypeORM
│ │ │ │
│ ▼ │ ▼
│ better-sqlite3 │ better-sqlite3
│ (DATABASE_PATH) │ (DATABASE_PATH, default ./data/db.sqlite)
├── /api/docs, /api/docs-json ── Swagger UI (OpenAPI 3.1) ├── /api/docs, /api/docs-json ── Swagger UI (OpenAPI 3.1)
├── /uploads/* ── static file server (UPLOAD_DIR) ├── /uploads/* ── static file server (UPLOAD_DIR, default ./data/uploads)
└── /* ── SPA fallback (FRONTEND_DIST/index.html) └── /* ── SPA fallback (FRONTEND_DIST/index.html)
``` ```
+2 -1
View File
@@ -8,7 +8,8 @@ timestamp: 2026-07-22T16:44:54Z
# Purpose # Purpose
Some persistent `/data/hipctf/db.sqlite` databases were created before Some persistent HIPCTF databases (default path
[`./data/db.sqlite`](/database/schema.md)) were created before
the canonical six system categories existed. They contain a legacy the canonical six system categories existed. They contain a legacy
six-column `category` table (no `created_at` / `updated_at`) and six-column `category` table (no `created_at` / `updated_at`) and
system rows whose `system_key` / `abbreviation` no longer match the system rows whose `system_key` / `abbreviation` no longer match the
+3 -2
View File
@@ -10,8 +10,9 @@ timestamp: 2026-07-22T16:44:54Z
HIPCTF uses **SQLite via better-sqlite3** with TypeORM migrations. The HIPCTF uses **SQLite via better-sqlite3** with TypeORM migrations. The
database is a single file (`DATABASE_PATH`, default database is a single file (`DATABASE_PATH`, default
`/data/hipctf/db.sqlite`) running in **WAL journal mode** for better `./data/db.sqlite`, resolved relative to the process working directory)
concurrent read/write performance. running in **WAL journal mode** for better concurrent read/write
performance.
The schema is created by a single migration The schema is created by a single migration
(`backend/src/database/migrations/1700000000000-InitSchema.ts`) and seeded (`backend/src/database/migrations/1700000000000-InitSchema.ts`) and seeded
+119
View File
@@ -0,0 +1,119 @@
---
type: guide
title: Local Development Workflow
description: How to run the backend and frontend together in development, including the root dev script, Angular dev-server proxy, and project-local data directory.
tags: [guide, dev, dev-server, proxy, concurrently, setup, tester]
timestamp: 2026-07-22T19:54:00Z
---
# Overview
The HIPCTF monorepo ships a single root command — `npm run dev` — that
boots the NestJS backend and the Angular dev server in parallel, with
the Angular dev server proxying `/api` and `/uploads` calls to the
backend on port 3000. All persistent runtime files (SQLite database,
uploaded icons / attachments / logos) live under the project-local
`./data/` directory.
# How to start the full stack (tester steps)
1. From the repository root, install workspace dependencies once:
```
npm ci
```
2. Start both servers in parallel:
```
npm run dev
```
This uses `concurrently` to run:
* `npm --workspace backend run start:dev` (NestJS watch mode on `http://localhost:3000`)
* `npm --workspace frontend run start` (Angular dev server on `http://localhost:4200`)
Process names `backend` and `frontend` are prefixed per output line.
If either process exits with a non-zero status, the other is killed
(`--kill-others-on-fail`).
3. Open the browser:
* **Frontend (preferred for app work):** `http://localhost:4200/`
* **Backend (single-port mode, serves built SPA later):** `http://localhost:3000/`
4. To run them individually during debugging:
```
npm run dev:backend
npm run dev:frontend
```
# Project-local data directory
| Path | Purpose | Backed by env var |
|-------------------|-------------------------------------------------------|---------------------|
| `./data/` | Root runtime data directory (gitignored). | — |
| `./data/db.sqlite`| SQLite database file (created on first boot). | `DATABASE_PATH` |
| `./data/uploads/` | Uploaded category icons, challenge files, site logos. | `UPLOAD_DIR` |
Both defaults are declared in `backend/src/config/env.schema.ts` and
re-declared as fallbacks in every backend code path that calls
`ConfigService.get` so direct/unit construction cannot silently revert
to the legacy absolute paths. Relative paths are resolved with
`path.resolve` against the process working directory — when launched
via the root scripts, that is the repository root.
The legacy absolute defaults (`/data/hipctf/db.sqlite`,
`/data/hipctf/uploads`) have been removed; set `DATABASE_PATH` and
`UPLOAD_DIR` explicitly if you need to point at an external location
(e.g. a mounted volume in production).
The data directory is created automatically:
* `DatabaseModule` ensures the parent directory of `DATABASE_PATH`
exists before connecting.
* `main.ts`, `UploadsController`, `buildMulter`, and
`UploadsStaticMiddleware` all `mkdir -p` the upload directory on
startup.
* `setup.sh` creates `./data/uploads` before any build so first-boot
Multer writes never fail.
# Angular dev-server proxy
`frontend/proxy.conf.json` is wired into the `serve` target in
`frontend/angular.json` so relative URLs from the SPA hit the backend
without CORS prompts:
| Origin path | Target | Notes |
|-------------|-------------------------|--------------------------------------------------------|
| `/api` | `http://localhost:3000` | All REST controllers + SSE endpoints. `changeOrigin: true`. |
| `/uploads` | `http://localhost:3000` | Static files served by `UploadsStaticMiddleware`. |
The proxy is **development-only.** In production (`npm start` /
`backend/dist/main.js`) the backend serves the built SPA directly and
no proxy is involved.
# Root scripts
| Script | What it does |
|---------------------|--------------------------------------------------------------------|
| `npm run dev` | Start backend + frontend together via `concurrently`. |
| `npm run dev:backend` | Start only the NestJS backend in watch mode. |
| `npm run dev:frontend` | Start only the Angular dev server. |
| `npm start` | Run the **production** backend (`node backend/dist/main.js`). |
| `npm run build` | Build both workspaces (frontend first, then backend). |
| `npm run start:dev` | Alias for `npm run dev` (kept for backwards compatibility). |
| `npm test` | Run the full Jest project (backend + frontend). |
# Expected behavior (tester)
* `npm run dev` displays interleaved backend and frontend logs, each
prefixed with the process name and a color.
* The Angular dev server prints `Application bundle generation complete`
within a few seconds and the page is reachable at
`http://localhost:4200/`.
* Visiting `http://localhost:4200/` triggers
`GET /api/v1/bootstrap` (proxied to port 3000) and shows the
appropriate public, login, or bootstrap page.
* Uploads (e.g. category icons via the admin UI) land under
`./data/uploads/` and are immediately readable from the dev frontend
via `/uploads/...` (proxied).
* Pressing `Ctrl+C` once terminates both processes cleanly.
# See also
- [System Overview](/architecture/overview.md)
- [Database Schema Overview](/database/schema.md)
- [Uploads Endpoints](/api/uploads.md)
- [Key Files Index](/architecture/key-files.md)
+4 -1
View File
@@ -11,7 +11,7 @@ scoreboard, an event window with a public countdown, theming, and admin
controls. controls.
The docs below are organized by purpose so agents can pull just the slice The docs below are organized by purpose so agents can pull just the slice
they need. Last regenerated 2026-07-22T19:18:00Z. they need. Last regenerated 2026-07-22T19:54:00Z.
# Architecture # Architecture
@@ -80,6 +80,9 @@ they need. Last regenerated 2026-07-22T19:18:00Z.
* [Cross-Tab Authenticated Shell Invalidation](/guides/cross-tab-invalidation.md) - * [Cross-Tab Authenticated Shell Invalidation](/guides/cross-tab-invalidation.md) -
How a logout in one tab, or an unauthorized SSE response, instantly clears How a logout in one tab, or an unauthorized SSE response, instantly clears
and redirects every other open tab of the SPA. and redirects every other open tab of the SPA.
* [Local Development Workflow](/guides/dev-workflow.md) - How to run the
backend and frontend together (`npm run dev`), the Angular dev-server
proxy, and the project-local `./data/` directory.
* [Session Restoration on Reload](/guides/session-restoration.md) - How * [Session Restoration on Reload](/guides/session-restoration.md) - How
the SPA keeps a user signed in across hard refreshes and how the the SPA keeps a user signed in across hard refreshes and how the
guards wait for bootstrap + auth hydration before deciding where to guards wait for bootstrap + auth hydration before deciding where to