docs: update documentation to OKF v0.1 format

This commit is contained in:
OpenVelo Agent
2026-07-22 14:52:57 +00:00
parent 3cf86b6233
commit 1858121f75
4 changed files with 36 additions and 18 deletions
+3 -3
View File
@@ -3,7 +3,7 @@ type: database
title: Challenge Tables title: Challenge Tables
description: category, challenge, challenge_file, and solve tables — how CTF challenges and scoring are stored. description: category, challenge, challenge_file, and solve tables — how CTF challenges and scoring are stored.
tags: [database, challenge, category, solve] tags: [database, challenge, category, solve]
timestamp: 2026-07-21T14:18:00Z timestamp: 2026-07-22T14:50:25Z
--- ---
# Tables # Tables
@@ -18,8 +18,8 @@ timestamp: 2026-07-21T14:18:00Z
| `abbreviation` | TEXT | Short label (e.g. `CRY`), 26 chars, server-uppercased. Globally unique — enforced by `uq_category_abbreviation`. | | `abbreviation` | TEXT | Short label (e.g. `CRY`), 26 chars, server-uppercased. Globally unique — enforced by `uq_category_abbreviation`. |
| `description` | TEXT | Optional description. | | `description` | TEXT | Optional description. |
| `icon_path` | TEXT | Default icon URL (e.g. `/uploads/icons/CRY.png`). | | `icon_path` | TEXT | Default icon URL (e.g. `/uploads/icons/CRY.png`). |
| `created_at` | TEXT | ISO 8601 timestamp the row was created (added by `AddCategoryTimestampsAndUniqueAbbrev1700000000200`). | | `created_at` | TEXT | ISO 8601 timestamp the row was created. Declared in the initial `InitSchema1700000000000` migration (defaulting to `strftime('%Y-%m-%dT%H:%M:%fZ','now')`); the `AddCategoryTimestampsAndUniqueAbbrev1700000000200` migration adds it as a no-op for older pre-existing databases. |
| `updated_at` | TEXT | ISO 8601 timestamp the row was last updated (added by the same migration; bumped on `PUT /api/v1/admin/categories/:id`). | | `updated_at` | TEXT | ISO 8601 timestamp the row was last updated (bumped on `PUT /api/v1/admin/categories/:id`). Same provenance as `created_at`. |
System rows are seeded by the System rows are seeded by the
`UpdateSystemCategoryKeys1700000000300` migration so the canonical `UpdateSystemCategoryKeys1700000000300` migration so the canonical
+7 -1
View File
@@ -3,7 +3,7 @@ type: database
title: Database Schema Overview title: Database Schema Overview
description: SQLite (better-sqlite3) schema for HIPCTF: tables, relationships, indexes, and WAL journal mode. description: SQLite (better-sqlite3) schema for HIPCTF: tables, relationships, indexes, and WAL journal mode.
tags: [database, sqlite, typeorm, schema] tags: [database, sqlite, typeorm, schema]
timestamp: 2026-07-21T14:18:00Z timestamp: 2026-07-22T14:50:25Z
--- ---
# Overview # Overview
@@ -17,6 +17,12 @@ 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
by a second migration by a second migration
(`backend/src/database/migrations/1700000000100-SeedSystemData.ts`). (`backend/src/database/migrations/1700000000100-SeedSystemData.ts`).
The initial migration declares every column used by the entities
(including `category.created_at` and `category.updated_at`), so the
later `AddCategoryTimestampsAndUniqueAbbrev1700000000200` and
`UpdateSystemCategoryKeys1700000000300` migrations only patch legacy
databases that pre-date those columns and reseed the canonical system
rows.
# Tables # Tables
+25 -13
View File
@@ -3,7 +3,7 @@ type: guide
title: Admin — General Settings title: Admin — General Settings
description: How an admin edits required platform-wide settings, including the validated event window, from the /admin/general page. description: How an admin edits required platform-wide settings, including the validated event window, from the /admin/general page.
tags: [guide, admin, settings, general, tester, datetime, validation] tags: [guide, admin, settings, general, tester, datetime, validation]
timestamp: 2026-07-22T14:24:08Z timestamp: 2026-07-22T14:50:25Z
--- ---
# When this view is available # When this view is available
@@ -17,7 +17,7 @@ by navigating directly to the URL.
|------------------|----------------------------------------------------------------------------|------------------------------------------------| |------------------|----------------------------------------------------------------------------|------------------------------------------------|
| Client route | `frontend/src/app/app.routes.ts` | `/admin/general` child of `adminGuard`. | | Client route | `frontend/src/app/app.routes.ts` | `/admin/general` child of `adminGuard`. |
| Client component | `frontend/src/app/features/admin/general.component.ts` | `AdminGeneralComponent.ngOnInit` fetches settings + themes. | | Client component | `frontend/src/app/features/admin/general.component.ts` | `AdminGeneralComponent.ngOnInit` fetches settings + themes. |
| Client predicate | `frontend/src/app/features/admin/general.pure.ts` (`deriveEventState`, `pageTitleError`, `pageTitleMessage`) | Pure helpers for event-state derivation and Page-title error/message mapping. | | Client predicate | `frontend/src/app/features/admin/general.pure.ts` (`deriveEventState`, `pageTitleError`, `pageTitleMessage`, `eventEndFieldMessage`) | Pure helpers for event-state derivation, Page-title error/message mapping, and the merged Event End field message (per-field `invalidDatetime` + cross-field `endBeforeStart`). |
| Server route | `backend/src/modules/admin/admin-general.controller.ts` | `GET/PUT /api/v1/admin/general/settings` + `GET /api/v1/admin/general/themes`. | | Server route | `backend/src/modules/admin/admin-general.controller.ts` | `GET/PUT /api/v1/admin/general/settings` + `GET /api/v1/admin/general/themes`. |
# How to access (tester steps) # How to access (tester steps)
@@ -43,7 +43,7 @@ The page is a single reactive form with these controls (every
| Logo upload status | `general-logo-uploading` / `general-logo-error` / `general-logo-current` | — | Inline status text under the file picker. | | Logo upload status | `general-logo-uploading` / `general-logo-error` / `general-logo-current` | — | Inline status text under the file picker. |
| Global theme | `general-themeKey` | `themeKey` | `<select>` populated from `/themes`. Value is one of `THEME_IDS`. | | Global theme | `general-themeKey` | `themeKey` | `<select>` populated from `/themes`. Value is one of `THEME_IDS`. |
| Event start (UTC) | `general-eventStart` | `eventStartUtc` | Required valid ISO-8601 datetime. Empty or malformed input renders `general-eventStart-error` and disables Save. | | Event start (UTC) | `general-eventStart` | `eventStartUtc` | Required valid ISO-8601 datetime. Empty or malformed input renders `general-eventStart-error` and disables Save. |
| Event end (UTC) | `general-eventEnd` | `eventEndUtc` | Required valid ISO-8601 datetime. Empty or malformed input renders `general-eventEnd-error`; it must also be strictly after Event start (`general-endBeforeStart`). | | Event end (UTC) | `general-eventEnd` | `eventEndUtc` | Required valid ISO-8601 datetime. Empty or malformed input renders `general-eventEnd-error`; it must also be strictly after Event start — when it is not, the same `general-eventEnd-error` region displays "Event end must be after event start." |
| Default challenge IP | `general-defaultIp` | `defaultChallengeIp` | Required, max 255 chars. | | Default challenge IP | `general-defaultIp` | `defaultChallengeIp` | Required, max 255 chars. |
| Enable registrations | `general-registrations` | `registrationsEnabled` | Boolean checkbox. When `false`, the public register endpoint returns `REGISTRATIONS_DISABLED`. | | Enable registrations | `general-registrations` | `registrationsEnabled` | Boolean checkbox. When `false`, the public register endpoint returns `REGISTRATIONS_DISABLED`. |
| Welcome description | `general-welcome` | `welcomeMarkdown` | Multi-line textarea; a live preview is rendered into `general-welcome-preview`. | | Welcome description | `general-welcome` | `welcomeMarkdown` | Multi-line textarea; a live preview is rendered into `general-welcome-preview`. |
@@ -71,9 +71,9 @@ The page is a single reactive form with these controls (every
* `start <= now < end``RUNNING` * `start <= now < end``RUNNING`
* `now >= end``STOPPED` * `now >= end``STOPPED`
* **End-before-start validation:** if the user picks an end that is not * **End-before-start validation:** if the user picks an end that is not
strictly after the start, the form becomes invalid and strictly after the start, the form becomes invalid and the
`general-endBeforeStart` appears under the end input. Save remains `general-eventEnd-error` region under the end input renders
disabled. "Event end must be after event start." Save remains disabled.
* **Per-field datetime validation:** clearing a field or supplying a value * **Per-field datetime validation:** clearing a field or supplying a value
that cannot be parsed as an ISO-8601 datetime makes that control invalid. that cannot be parsed as an ISO-8601 datetime makes that control invalid.
The affected input receives `aria-invalid="true"`, references its inline The affected input receives `aria-invalid="true"`, references its inline
@@ -136,6 +136,16 @@ two pure helpers exported from
* `datetimeMessage(fieldLabel, value, controlErrors)` — renders the * `datetimeMessage(fieldLabel, value, controlErrors)` — renders the
human-readable message `"<Field> must be a valid ISO-8601 datetime."` human-readable message `"<Field> must be a valid ISO-8601 datetime."`
when `invalidDatetime` is set or when the raw value is unparseable. when `invalidDatetime` is set or when the raw value is unparseable.
* `eventEndFieldMessage(controlErrors, crossFieldErrors)` — returns the
canonical message for the Event End field's own error region. It
prefers the per-field ISO message
(`"Event end must be a valid ISO-8601 datetime."`) when
`controlErrors?.['invalidDatetime']` is set, otherwise it surfaces the
cross-field `endBeforeStart` message
(`"Event end must be after event start."`), otherwise `null`. The
component reads this helper through the `eventEndFieldMessageText`
computed signal so both error kinds render inside the single
`general-eventEnd-error` element.
The component wires both controls (`eventStartUtc`, `eventEndUtc`) with The component wires both controls (`eventStartUtc`, `eventEndUtc`) with
this validator and keeps three local `signal`s per field — `Value`, this validator and keeps three local `signal`s per field — `Value`,
@@ -160,11 +170,14 @@ The error is shown only when the control is both `touched || dirty`
AND `invalid`, so the inputs do not flash errors on initial load. After AND `invalid`, so the inputs do not flash errors on initial load. After
a successful Save, both controls are reset to untouched/pristine via a successful Save, both controls are reset to untouched/pristine via
`resetTouchedState()` and their `TouchedOrDirty` signals are cleared. `resetTouchedState()` and their `TouchedOrDirty` signals are cleared.
The cross-field `endBeforeStart` error (`general-endBeforeStart`) is The cross-field `endBeforeStart` error is emitted by the form-level
emitted by the form-level validator whenever both valid timestamps are validator whenever both valid timestamps are present and end is not
present and end is not strictly after start. The Event end input also strictly after start. The Event end input receives `aria-invalid="true"`,
receives `aria-invalid="true"`, references both possible error elements, references `general-eventEnd-error` via `aria-describedby`, and exposes
and exposes `Event end must be after event start.` as its title. `Event end must be after event start.` as its title — the message itself
is rendered inside the per-field error region
(`data-testid="general-eventEnd-error"`) by the
`eventEndFieldMessage` helper.
# Visual elements # Visual elements
@@ -175,9 +188,8 @@ and exposes `Event end must be after event start.` as its title.
| Load error | `[data-testid="general-error"]` | | Load error | `[data-testid="general-error"]` |
| Form | `[data-testid="general-form"]` | | Form | `[data-testid="general-form"]` |
| Welcome preview | `[data-testid="general-welcome-preview"]` | | Welcome preview | `[data-testid="general-welcome-preview"]` |
| End-before-start message | `[data-testid="general-endBeforeStart"]` |
| Event start inline error | `[data-testid="general-eventStart-error"]` | | Event start inline error | `[data-testid="general-eventStart-error"]` |
| Event end inline error | `[data-testid="general-eventEnd-error"]` | | Event end inline error | `[data-testid="general-eventEnd-error"]` (renders both the per-field `invalidDatetime` message and the cross-field `endBeforeStart` "Event end must be after event start." message) |
| Page-title inline error | `[data-testid="general-pageTitle-error"]` | | Page-title inline error | `[data-testid="general-pageTitle-error"]` |
# Architecture map # Architecture map
+1 -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-22T14:24:08Z. they need. Last regenerated 2026-07-22T14:50:25Z.
# Architecture # Architecture