From c80905b53808a11756204f700664004378b5a772 Mon Sep 17 00:00:00 2001 From: OpenVelo Agent Date: Tue, 21 Jul 2026 16:49:46 +0000 Subject: [PATCH] docs: update documentation to OKF v0.1 format --- docs/api/setup.md | 3 +- docs/architecture/frontend-structure.md | 4 +- docs/architecture/key-files.md | 4 +- docs/guides/bootstrap.md | 5 +- docs/guides/setup-field-errors.md | 95 +++++++++++++++++++++++++ docs/index.md | 5 +- 6 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 docs/guides/setup-field-errors.md diff --git a/docs/api/setup.md b/docs/api/setup.md index d3c1cea..c54867a 100644 --- a/docs/api/setup.md +++ b/docs/api/setup.md @@ -3,7 +3,7 @@ type: api title: Setup Endpoint description: Dedicated POST /api/v1/setup/create-admin endpoint used only while no administrator exists. tags: [api, setup, bootstrap, first-admin] -timestamp: 2026-07-21T16:23:40Z +timestamp: 2026-07-21T16:48:20Z --- # Endpoint @@ -76,5 +76,6 @@ non-retryable inline error and offer a Retry button for everything else. # See also - [First-Run Bootstrap Guide](/guides/bootstrap.md) +- [Setup Form Field Errors](/guides/setup-field-errors.md) - [Backend Module Map](/architecture/backend-modules.md) - [Bootstrap Service](/architecture/frontend-structure.md) \ No newline at end of file diff --git a/docs/architecture/frontend-structure.md b/docs/architecture/frontend-structure.md index 73da60f..eb46b7a 100644 --- a/docs/architecture/frontend-structure.md +++ b/docs/architecture/frontend-structure.md @@ -3,7 +3,7 @@ type: architecture title: Frontend Structure description: Angular routes, components, services, guards, and interceptors. tags: [architecture, frontend, angular] -timestamp: 2026-07-21T15:05:00Z +timestamp: 2026-07-21T16:48:20Z --- # Routes @@ -29,7 +29,7 @@ All components are standalone (no NgModules). Each component imports | `HomeComponent` | `frontend/src/app/features/home/home.component.ts` | Authenticated shell with header, conditional admin nav, and `` for children. | | `AdminUsersComponent` | `frontend/src/app/features/admin/admin-users.component.ts` | Admin-only user list rendered inside the home shell. | | `LoginComponent` | `frontend/src/app/features/auth/login.component.ts` | Username/password form. | -| `SetupCreateAdminComponent` | `frontend/src/app/features/setup/setup-create-admin.component.ts` | First-admin bootstrap modal with typed reactive form, validation messages, retry handling, session initialization, and redirect to `/admin`. | +| `SetupCreateAdminComponent` | `frontend/src/app/features/setup/setup-create-admin.component.ts` | First-admin bootstrap modal with typed reactive form, inline validation messages (via [the field-error helpers](/guides/setup-field-errors.md)), retry handling, session initialization, and redirect to `/admin`. | # Services diff --git a/docs/architecture/key-files.md b/docs/architecture/key-files.md index ce02e30..a83e7f2 100644 --- a/docs/architecture/key-files.md +++ b/docs/architecture/key-files.md @@ -3,7 +3,7 @@ type: architecture title: Key Files Index description: One-line responsibility for every important source file in the repository. tags: [architecture, index, key-files] -timestamp: 2026-07-21T15:05:00Z +timestamp: 2026-07-21T16:48:20Z --- # Backend @@ -123,6 +123,7 @@ timestamp: 2026-07-21T15:05:00Z | `frontend/src/app/features/setup/setup-create-admin.component.ts` | First-admin modal overlay (non-dismissible; typed reactive form). | | `frontend/src/app/features/setup/setup-create-admin.service.ts` | POSTs to `/api/v1/setup/create-admin` and tags the result with the error code. | | `frontend/src/app/features/setup/setup-create-admin.validators.ts` | Standalone `passwordMatchValidator` group-level reactive form validator. | +| `frontend/src/app/features/setup/setup-create-admin.field-errors.ts` | Pure `usernameError` / `passwordError` / `confirmError` helpers that turn reactive-form state into the inline validation messages rendered next to each input. | | `frontend/src/app/features/home/home.component.ts` | Authenticated shell: header + conditional admin nav + ``. | | `frontend/src/app/features/home/home.shell.ts` | Pure `shouldShowAdminNav({isAuthenticated, role})` predicate (unit-tested). | @@ -135,6 +136,7 @@ timestamp: 2026-07-21T15:05:00Z | `tests/frontend/admin-shell.spec.ts` | Unit tests for `shouldShowAdminNav` predicate. | | `tests/frontend/admin-navigation.spec.ts` | Tests for admin guard decision + nav-link rendering. | | `tests/frontend/auth-restore.spec.ts` | Round-trips `auth.session-storage` helpers + refresh success/failure paths. | +| `tests/frontend/setup-create-admin.spec.ts` | Pure-Jest tests for `passwordMatchValidator` and the three field-error helpers (`usernameError`, `passwordError`, `confirmError`). | | `tests/frontend/guard-bootstrap-race.spec.ts` | Pins `decideAuthRedirect` so a refresh on a deep link never flashes `/bootstrap` or `/login` while auth is hydrating. | | `tests/backend/csrf-client.ts` | Test helper for CSRF flow. | | `tests/backend/db-helper.ts` | Test helper for spinning up an isolated DB. | diff --git a/docs/guides/bootstrap.md b/docs/guides/bootstrap.md index c959f2b..9ece7bd 100644 --- a/docs/guides/bootstrap.md +++ b/docs/guides/bootstrap.md @@ -3,7 +3,7 @@ type: guide title: First-Run Bootstrap description: How a fresh HIPCTF instance is initialized by the very first administrator. tags: [guide, bootstrap, first-admin, onboarding, tester] -timestamp: 2026-07-21T16:23:40Z +timestamp: 2026-07-21T16:48:20Z --- # When this flow runs @@ -70,7 +70,8 @@ The modal **cannot** be dismissed by the user: | Modal overlay | `.overlay` | Full-screen backdrop. | | Modal card | `.modal[role="dialog"]` | Contains the form; stops click propagation. | | Username input | `[data-testid="setup-username"]` | Reactive control with length/pattern rules. | -| Password input | `[data-testid="setup-password"]` | Reactive control. | +| Password input | `[data-testid="setup-password"]` | Reactive control; shows inline error on touch when empty. | +| Password error | `[data-testid="setup-password-error"]` | Renders `passwordError()` (currently `required`). | | Confirm input | `[data-testid="setup-password-confirm"]` | Reactive control. | | Submit button | `[data-testid="setup-submit"]` | Triggers validation even when invalid; disabled only while submitting. | | Server error alert | `[data-testid="setup-server-error"]` | Displays `serverError()`. | diff --git a/docs/guides/setup-field-errors.md b/docs/guides/setup-field-errors.md new file mode 100644 index 0000000..4f900ef --- /dev/null +++ b/docs/guides/setup-field-errors.md @@ -0,0 +1,95 @@ +--- +type: guide +title: Setup Form Field Errors +description: Pure error-computation functions that drive the inline validation messages on the first-admin modal. +tags: [setup, validation, forms, frontend] +timestamp: 2026-07-21T16:48:20Z +--- + +# Purpose + +The three pure helpers exported by +`frontend/src/app/features/setup/setup-create-admin.field-errors.ts` +turn the raw Angular reactive-form control state into the user-facing +strings shown beside each input on the first-admin modal. Keeping them +as standalone functions (instead of `computed()` signals inside the +component) makes them trivially unit-testable in isolation — see +`tests/frontend/setup-create-admin.spec.ts`. + +# Helpers + +| Function | Returns | Reads | +|-----------------|---------------------------------------------------------|------------------------------------------------------------------------| +| `usernameError` | `string \| null` | `value`, `touched`, plus `errors` keys `required`/`minlength`/`maxlength`/`pattern`. | +| `passwordError` | `string \| null` | `value`, `touched`, plus `errors.required`. | +| `confirmError` | `string \| null` | `value`, `touched`, `errors.required`, and the group-level `groupMismatch` flag from [the password-match validator](/architecture/key-files.md). | + +All three return `null` when the field is not yet `touched` (or, for +`confirmError`, when no group-level mismatch has been raised), so the +UI stays clean until the user has interacted with the form. + +# Inputs + +```ts +export interface FieldErrorContext { + value: string; + touched: boolean; + errors: Partial> | null; + groupMismatch?: boolean; +} + +export type FieldErrorKey = + | 'required' + | 'minlength' + | 'maxlength' + | 'pattern' + | 'passwordMismatch'; +``` + +# Examples + +```ts +usernameError({ + value: 'ab', + touched: true, + errors: { minlength: true }, +}); +// -> 'Username must be at least 3 characters' + +confirmError({ + value: 'hunter2', + touched: true, + errors: null, + groupMismatch: true, +}); +// -> 'Passwords do not match' + +passwordError({ + value: '', + touched: true, + errors: { required: true }, +}); +// -> 'Password is required' +``` + +# Wiring + +* `SetupCreateAdminComponent` (`frontend/src/app/features/setup/setup-create-admin.component.ts`) + binds the three helpers to template method calls (`usernameError()`, + `passwordError()`, `confirmError()`) that read the corresponding + `FormControl` and pass its current state. +* The template + (`frontend/src/app/features/setup/setup-create-admin.component.html`) + renders the returned string inside a `` + with `data-testid="setup-{username|password|confirm}-error"`, and + mirrors the result on the input via `[attr.aria-invalid]`. +* `tests/frontend/setup-create-admin.spec.ts` exercises every code path + of the three helpers directly — no Angular TestBed is required. + +# See also + +- [First-Run Bootstrap](/guides/bootstrap.md) — how the helpers surface + to the operator. +- [Setup Endpoint](/api/setup.md) — server-side validation that + mirrors these messages. +- [Key Files Index](/architecture/key-files.md) \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 0f07ac9..3c58bc8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ scoreboard, an event window with a public countdown, theming, and admin controls. The docs below are organized by purpose so agents can pull just the slice -they need. Last regenerated 2026-07-21T16:23:40Z. +they need. Last regenerated 2026-07-21T16:48:20Z. # Architecture @@ -52,6 +52,9 @@ they need. Last regenerated 2026-07-21T16:23:40Z. * [First-Run Bootstrap](/guides/bootstrap.md) - How a fresh instance is initialized by the very first admin via the non-dismissible modal. +* [Setup Form Field Errors](/guides/setup-field-errors.md) - Pure + helpers that translate reactive-form state into the inline validation + messages on the first-admin modal. * [Admin Shell & User Management](/guides/admin-shell.md) - How admins navigate the post-login shell and reach the user-management area. * [Session Restoration on Reload](/guides/session-restoration.md) - How