docs: update documentation to OKF v0.1 format
This commit is contained in:
@@ -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`), 2–6 chars, server-uppercased. Globally unique — enforced by `uq_category_abbreviation`. |
|
| `abbreviation` | TEXT | Short label (e.g. `CRY`), 2–6 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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user