docs: update documentation to OKF v0.1 format

This commit is contained in:
OpenVelo Agent
2026-07-22 15:47:01 +00:00
parent 2a6182b938
commit a39a4892b0
4 changed files with 62 additions and 11 deletions
+8 -3
View File
@@ -2,8 +2,8 @@
type: api type: api
title: Admin Endpoints title: Admin Endpoints
description: Admin-only endpoints for user management, required general settings, categories, and supporting uploads. description: Admin-only endpoints for user management, required general settings, categories, and supporting uploads.
tags: [api, admin, users, general, categories] tags: [api, admin, users, general, categories, default-challenge-ip, ip-hostname, validation]
timestamp: 2026-07-22T14:24:08Z timestamp: 2026-07-22T15:46:18Z
--- ---
# Endpoints # Endpoints
@@ -53,7 +53,12 @@ removes the row.
`superRefine` additionally requires `eventEndUtc > eventStartUtc` and `superRefine` additionally requires `eventEndUtc > eventStartUtc` and
reports `eventEndUtc must be strictly after eventStartUtc` on the end reports `eventEndUtc must be strictly after eventStartUtc` on the end
field when both values parse but are out of order. field when both values parse but are out of order.
* `defaultChallengeIp` 1255 chars * `defaultChallengeIp` is trimmed server-side; empty/whitespace-only values
are rejected (`defaultChallengeIp is required and cannot contain only
whitespace`), and the trimmed value must be a complete IPv4 address or a
valid hostname, otherwise `400 VALIDATION_FAILED` with a per-field
`defaultChallengeIp` issue (`defaultChallengeIp must be a valid IPv4
address or hostname`). Maximum length is 255 characters.
* `registrationsEnabled` boolean * `registrationsEnabled` boolean
On success the handler persists every field via `SettingsService`, On success the handler persists every field via `SettingsService`,
+4 -4
View File
@@ -2,8 +2,8 @@
type: architecture type: architecture
title: Key Files Index title: Key Files Index
description: One-line responsibility for important source and contract-test files, including strict event-window validation. description: One-line responsibility for important source and contract-test files, including strict event-window validation.
tags: [architecture, key-files, event-window, validation] tags: [architecture, key-files, event-window, validation, default-challenge-ip]
timestamp: 2026-07-22T14:24:08Z timestamp: 2026-07-22T15:46:18Z
--- ---
# Backend # Backend
@@ -49,8 +49,8 @@ timestamp: 2026-07-22T14:24:08Z
| `frontend/src/app/features/shell/tabs/quick-tabs.component.ts` | Main shell navigation tabs. | | `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/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/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/general.pure.ts` | Pure General Settings helpers, including required datetime validation, field messages, UTC conversion, and end-after-start validation. | | `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, and event-window ordering. | | `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/authenticated-event-source.spec.ts` | Tests SSE authorization, frame transport behavior, and the `401`/`403` unauthorized path. | | `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/auth-session-events.spec.ts` | Pure tests for cross-tab invalidation message encoding, payload validation, and `storage`-event filtering. |
+49 -3
View File
@@ -2,8 +2,8 @@
type: guide 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, utc, timezone] tags: [guide, admin, settings, general, tester, datetime, validation, utc, timezone, default-challenge-ip, ip-hostname]
timestamp: 2026-07-22T15:09:39Z timestamp: 2026-07-22T15:46:18Z
--- ---
# When this view is available # When this view is available
@@ -44,7 +44,7 @@ The page is a single reactive form with these controls (every
| 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 — when it is not, the same `general-eventEnd-error` region displays "Event end must be after event start." | | 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, non-blank, max 255 chars after trimming; must be a complete IPv4 address or a valid hostname; trimmed server-side. Renders `general-defaultIp-error` for empty/whitespace or malformed input. |
| 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`. |
| Event controls | `general-event-toggle` | (derived) | Disabled button whose text is the derived event state (`UNCONFIGURED` / `COUNTDOWN` / `RUNNING` / `STOPPED`). | | Event controls | `general-event-toggle` | (derived) | Disabled button whose text is the derived event state (`UNCONFIGURED` / `COUNTDOWN` / `RUNNING` / `STOPPED`). |
@@ -124,6 +124,51 @@ Save, the control is reset to untouched/pristine and the
`pageTitleTouchedOrDirty` signal is cleared, so reloading valid `pageTitleTouchedOrDirty` signal is cleared, so reloading valid
settings does not flash a stale error. settings does not flash a stale error.
# Default challenge IP inline error message
The inline error element under the Default challenge IP field
(`general-defaultIp-error`) is driven by the pure helpers exported
from `frontend/src/app/features/admin/general.pure.ts`:
* `isValidDefaultChallengeAddress(value)` — returns `true` only for a
complete IPv4 address (four 0255 octets, no leading zeros on a
multi-digit octet) or a valid RFC-1123 hostname.
* `defaultChallengeAddressError(value)` — returns `'required'` for
empty/whitespace-only input and `'format'` for malformed addresses,
otherwise `null`.
* `defaultChallengeAddressMessage(value, controlErrors)` — renders the
human-readable text used by the inline region.
* `normalizeDefaultChallengeAddress(value)` — trims surrounding
whitespace from the value submitted to the backend.
The component keeps three local `signal`s — `defaultChallengeIpValue`,
`defaultChallengeIpInvalid`, and `defaultChallengeIpTouchedOrDirty`
mirroring the Page-title pattern. The reactive-form control uses a
custom validator that returns `{ defaultChallengeAddressFormat: true }`
for malformed addresses (alongside `Validators.required` for the empty
case), and the `computed` signals `showDefaultChallengeIpError` and
`defaultChallengeIpMessage` drive:
* `[attr.aria-invalid]` and `[attr.aria-describedby]` on the input so
assistive tech is informed the instant the field goes invalid.
* An `@if` block that renders the inline `<div class="field-error">`
with `data-testid="general-defaultIp-error"`.
| Condition | Message |
|------------------------------------------------------------|--------------------------------------------------------|
| Empty or whitespace-only value | `Default challenge IP is required and cannot contain only whitespace.` |
| Incomplete IPv4 (`10.0.0.`, `10.0.0`), out-of-range octets, or malformed hostname | `Default challenge IP must be a valid IPv4 address or hostname.` |
| Valid IPv4 or hostname | `null` (no error rendered; Save enabled). |
After a successful Save the component trims the value through
`normalizeDefaultChallengeAddress`, persists the canonical form via
`PUT /api/v1/admin/general/settings`, and resets the control to
untouched/pristine, so a freshly-loaded valid value does not flash a
stale error. The server `GeneralSettingsSchema` performs the same
trim and format check, so invalid values return `400 VALIDATION_FAILED`
with a per-field `defaultChallengeIp` issue and the stored value is
unchanged.
# Event start / end inline error messages # Event start / end inline error messages
The inline error elements under the Event start and Event end inputs The inline error elements under the Event start and Event end inputs
@@ -248,6 +293,7 @@ suite, with cases that lock in:
| 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"]` (renders both the per-field `invalidDatetime` message and the cross-field `endBeforeStart` "Event end must be after event start." message) | | 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"]` |
| Default challenge IP inline error | `[data-testid="general-defaultIp-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-22T15:09:39Z. they need. Last regenerated 2026-07-22T15:46:18Z.
# Architecture # Architecture