From c434e5d3a2cf09f9a3f2bf102ebf0259897ee867 Mon Sep 17 00:00:00 2001 From: OpenVelo Agent Date: Thu, 23 Jul 2026 03:11:16 +0000 Subject: [PATCH] docs: update documentation to OKF v0.1 format --- docs/architecture/frontend-structure.md | 2 +- docs/architecture/key-files.md | 7 ++++--- docs/guides/challenges-board.md | 8 +++++--- docs/guides/event-window.md | 7 +++++-- docs/index.md | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/architecture/frontend-structure.md b/docs/architecture/frontend-structure.md index eaba6c0..46d79f8 100644 --- a/docs/architecture/frontend-structure.md +++ b/docs/architecture/frontend-structure.md @@ -89,7 +89,7 @@ single path. | `EventState` | Union `'running' \| 'countdown' \| 'stopped' \| 'unconfigured'`. | | `EventStatePayload` | Server-pushed event window payload shape. | | `EventSourceLike` | Minimal interface for any SSE transport the store can drive. | -| `formatDdHhMm(seconds)` | Pure `DD:HH:mm` formatter. | +| `formatDdHhMm(seconds)` | Pure `DD:HH:mm:ss` formatter (zero-padded, falls back to `00:00:00:00` for negative / non-finite input). | | `deriveCountdownText(state, start, end)` | Pure mapping from event window state to countdown label. | | `LED_COLOR_BY_STATE` | `Readonly>` mapping each state to its theme CSS variable (`var(--color-success)`, `--color-warning`, `--color-danger`, `--color-secondary`). | | `ledBackgroundColor(state)` | Pure accessor returning the `background-color` value for the LED element. | diff --git a/docs/architecture/key-files.md b/docs/architecture/key-files.md index 79beefc..428f882 100644 --- a/docs/architecture/key-files.md +++ b/docs/architecture/key-files.md @@ -59,7 +59,7 @@ timestamp: 2026-07-23T01:19:00Z | `frontend/src/app/core/services/bootstrap-event.service.ts` | Root-provided public SSE listener that subscribes to `/api/v1/event/stream`, filters `topic === 'general'` frames, and triggers `BootstrapService.refresh()` so the landing modal stays in sync with admin general-settings updates. | | `frontend/src/app/core/services/bootstrap-event.pure.ts` | Pure helpers for the public bootstrap SSE listener: `isBootstrapGeneralFrame` predicate, SSE line parser, and the `makeBootstrapEventSource` factory (fetch + `ReadableStream` opener with frame buffering and idempotent `close()`). | | `frontend/src/app/core/services/event-status.store.ts` | Event state signal store, one-second countdown timer, and the optional `onUnauthorized` callback wiring; exposes `start()`/`stop()`/`closeTransport()` for transport lifecycle and `subscribeReloadAtCountdownZero(handler)` (with `reloadAtCountdownZero(handler)` kept as a back-compat wrapper) so the reload handler is owned by its subscriber rather than the transport. | -| `frontend/src/app/core/services/event-status.pure.ts` | Event payload types, transport interface (including `'unauthorized'` listener), pure countdown helpers, and the `LED_COLOR_BY_STATE` map used by the shell LED. | +| `frontend/src/app/core/services/event-status.pure.ts` | Event payload types, transport interface (including `'unauthorized'` listener), pure countdown helpers (`formatDdHhMm` returns `DD:HH:mm:ss` and `deriveCountdownText`), and the `LED_COLOR_BY_STATE` map used by the shell LED. | | `frontend/src/app/features/home/home.component.ts` | Authenticated shell container; starts user and event state services, subscribes to peer invalidation, and navigates to `/login` when the session is invalidated elsewhere. | | `frontend/src/app/features/shell/header/shell-header.component.ts` | Shell title, status LED (size/shape only — color comes from the pure map via `[style.background-color]`), countdown, and user menu. | | `frontend/src/app/features/shell/tabs/quick-tabs.component.ts` | Main shell navigation tabs. | @@ -74,14 +74,15 @@ timestamp: 2026-07-23T01:19:00Z | `tests/frontend/admin-challenges-import-autoclose.spec.ts` | Pure helpers (`summarizeImportResult`, `importErrorMessage`) and modal auto-close branch for the confirmed-import handler. | | `frontend/src/app/features/challenges/challenges.page.ts` | `/challenges` smart page: gate logic (countdown/running/stopped/unconfigured), modal lifecycle, SSE wiring on `/api/v1/events`, and the page-owned countdown-zero reload (handler registered in the constructor with the disposer wired into `DestroyRef`). | | `frontend/src/app/features/challenges/challenges.store.ts` | Signal store: board, event state, per-card solve listeners, SSE solve-frame mutation, submit response application, stop() lifecycle. | -| `frontend/src/app/features/challenges/challenges.service.ts` | HTTP service for `/api/v1/challenges/{board,status,:id,:id/solves}` returning typed `ApiErrorEnvelope`s. | +| `frontend/src/app/features/challenges/challenges.service.ts` | HTTP service for `/api/v1/challenges/{board,status,:id,:id/solves}` returning typed `ApiErrorEnvelope`s. `getDetail` always requests `?include=solvers` so the modal can render the solvers list in one round-trip; `getBoard` only attaches `include=solvers` when the caller opts in. | | `frontend/src/app/features/challenges/challenges.pure.ts` | Pure types and helpers (`BoardCard`, `SolverRow`, `SolveEventPayload`, `parseSolveEvent`, `mergeSolveEventIntoSolvers`, `messageForSolveError`, `formatDdHhMm`). | | `frontend/src/app/features/challenges/category-column.component.ts` | Renders a single category column (header + cards) on the challenges board. | | `frontend/src/app/features/challenges/challenge-card.component.ts` | Renders a single challenge card on the board (difficulty, live points, solve count, `✓` when solved by the player). | | `frontend/src/app/features/challenges/challenge-modal.component.ts` | Challenge detail modal: description, flag form, awarded banner, solvers list, live-solve updates. | | `frontend/src/app/core/services/notification.service.ts` | Root-provided signal-backed store of `{ id, kind, message, ts }` records; `error()` / `info()` push, `dismiss(id)` / `clear()` remove. | | `frontend/src/app/core/interceptors/error-notification.interceptor.ts` | Translates `HttpErrorResponse` into friendly messages and pushes them to `NotificationService` (with suppression for `/api/v1/auth/{login,csrf,register}` and `/api/v1/challenges/status`). | -| `tests/frontend/challenges.pure.spec.ts` | Pure helpers: sorting, parsers, friendly error mapping, `formatDdHhMm`. | +| `tests/frontend/challenges.pure.spec.ts` | Pure helpers: sorting, parsers, friendly error mapping, `formatDdHhMm` (`DD:HH:mm:ss`). | +| `tests/frontend/challenges.service.spec.ts` | HTTP-service contract: `getDetail` URL-encodes the id, attaches `?include=solvers`, and forwards `withCredentials: true`. | | `tests/frontend/challenges.store.spec.ts` | Signal store: board mutation, live solve merge, listeners, `stop()`. | | `tests/frontend/notification-interceptor.spec.ts` | Interceptor suppression rules and friendly message mapping. | | `tests/backend/challenges-board.spec.ts` | Board query shape, ordering, `?include=solvers`. | diff --git a/docs/guides/challenges-board.md b/docs/guides/challenges-board.md index 4548ea0..09ed4a9 100644 --- a/docs/guides/challenges-board.md +++ b/docs/guides/challenges-board.md @@ -3,7 +3,7 @@ type: guide title: Challenges Board description: How a signed-in player navigates the `/challenges` page, opens a challenge modal, submits a flag, and watches live solve updates. tags: [guide, challenges, board, flag, score, sse, tester] -timestamp: 2026-07-23T00:10:00Z +timestamp: 2026-07-23T03:09:00Z --- # When this view is available @@ -66,7 +66,7 @@ renders `[data-testid="challenges-gate"]`: | Event state | Headline | Countdown text (`[data-testid="challenges-countdown"]`) | Helper label | |---------------|---------------------------|--------------------------------------------------------|-----------------------------------------------------| -| `countdown` | `Event starts in` | `DD:HH:mm` until `eventStartUtc` | `The board will be available once the event is running.` | +| `countdown` | `Event starts in` | `DD:HH:mm:ss` until `eventStartUtc` (ticks each second during the final minute so the player sees time elapse) | `The board will be available once the event is running.` | | `running` | _(grid shown instead)_ | — | — | | `stopped` | `Event ended` | `Event ended` | `The board is closed.` | | `unconfigured`| `Awaiting configuration` | empty | _(none)_ | @@ -159,7 +159,9 @@ destruction of the page the SSE source is closed via ## Countdown / stopped gate 1. Set `eventStartUtc` in the future; confirm the gate panel shows - `Event starts in` and the `DD:HH:mm` countdown. + `Event starts in` and the `DD:HH:mm:ss` countdown. Within the final + minute the seconds digit visibly ticks down (e.g. `00:00:00:24` → + `00:00:00:23` → …) so the player can see time elapse. 2. Wait for the countdown to hit zero; the SPA reloads and now shows the board. 3. Set `eventEndUtc` in the past; confirm the gate shows diff --git a/docs/guides/event-window.md b/docs/guides/event-window.md index 718641e..0434470 100644 --- a/docs/guides/event-window.md +++ b/docs/guides/event-window.md @@ -3,7 +3,7 @@ type: guide title: Event Window description: How the event window state machine is computed and surfaced via REST + SSE. tags: [guide, event, countdown, sse, state-machine] -timestamp: 2026-07-23T01:19:00Z +timestamp: 2026-07-23T03:09:00Z --- # Configuration @@ -73,7 +73,10 @@ The store: 3. Exposes `countdownText` (computed): `""` for `unconfigured`, `"Event ended"` for `stopped`, and `formatDdHhMm(seconds)` for `countdown` / `running`. The format helper lives in the pure module - `event-status.pure.ts` (`DD:HH:mm`, zero-padded). + `event-status.pure.ts` (`DD:HH:mm:ss`, zero-padded). The seconds + digit is driven by the local 1-second tick (and the SSE re-push + every 60 seconds) so the final minute of the countdown visibly + elapses second-by-second on the shell header. The header (`ShellHeaderComponent`) renders an LED with the `led-{state}` class so the colour reflects the current state (the diff --git a/docs/index.md b/docs/index.md index 5ee4244..8eae156 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-23T02:23:34Z. +they need. Last regenerated 2026-07-23T03:09:36Z. # Architecture