Files
HIPCTF2/docs/guides/authenticated-shell.md
T

107 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: guide
title: Authenticated Shell
description: How a signed-in user experiences the post-login shell, including authenticated event streaming.
tags: [guide, shell, header, sse, navigation, tester]
timestamp: 2026-07-22T09:22:34Z
---
# When this view is available
The authenticated shell is the post-login UI rendered by `HomeComponent`
(`frontend/src/app/features/home/home.component.ts`). It is gated by the client
`authGuard` and the JWT-protected `/api/v1/events/status` stream.
A user who is not signed in, or whose session has expired, is sent to `/login`
before the shell mounts.
# How to access (tester steps)
1. Ensure the instance is initialized. If not, follow [First-Run Bootstrap](/guides/bootstrap.md).
2. Sign in via `/login` as an admin or player.
3. Confirm the browser lands on `/challenges` and renders the shell.
# Expected behavior
## Header
| Element | Selector | Expected |
|---|---|---|
| Page title | `[data-testid="shell-title"]` | Shows the bootstrap `pageTitle`; clicking navigates to `/challenges`. |
| Active section | `[data-testid="shell-active-section"]` | Shows `Challenges`, `Scoreboard`, `Blog`, or `Admin` based on the URL. |
| Event LED | `[data-testid="shell-led"]` | A 10×10 circular dot whose color reflects the current event state. See [Event LED colors](#event-led-colors) below. |
| Countdown | `[data-testid="shell-countdown"]` | Displays `DD:HH:mm`, `Event ended`, or empty for an unconfigured event. |
| User menu | `[data-testid="user-menu-trigger"]` | Toggles rank, change-password, optional admin, and logout entries. |
# Event LED colors
The LED is rendered by `ShellHeaderComponent` as a `<span class="led">` with one of four state classes attached via `[class.led-<state>]`. Its component-scoped styling is declared in `frontend/src/app/features/shell/header/shell-header.component.ts` and is driven entirely by the existing theme color tokens — there is no per-state color in TypeScript.
| Event state | CSS class | Color token | Approx. hex | Visual |
|-------------------|-----------------------|-----------------------|-------------|--------|
| `countdown` | `led led-countdown` | `--color-warning` | `#f59e0b` | Yellow filled dot |
| `running` | `led led-running` | `--color-success` | `#10b981` | Green filled dot |
| `stopped` | `led led-stopped` | `--color-danger` | `#ef4444` | Red filled dot |
| `unconfigured` | `led led-unconfigured`| `--color-secondary` | `#64748b` | Neutral gray filled dot |
The base `.led` rule paints a 10×10 circular `inline-block`, so the LED
is always the same size and shape — only the background color changes
between states. The element also carries
`aria-label="Event status: <state>"` for assistive tech.
## Quick tabs
The tab strip `[data-testid="quick-tabs"]` contains `Challenges`, `Scoreboard`, and
`Blog`. Clicking a tab navigates to its matching route; the active tab is marked
with the active class.
# Live event window
1. `HomeComponent.ngOnInit()` starts `EventStatusStore` with
`AuthenticatedEventSourceService.open('/api/v1/events/status')`.
2. The transport uses `fetch`, sends `Accept: text/event-stream`, includes
`Authorization: Bearer <access-token>` when available, and sends credentials.
3. It parses SSE `event:` and `data:` lines, buffers frames until a message listener
is registered, and dispatches `MessageEvent` payloads.
4. The store applies each state frame and advances countdown values with a local
one-second tick between server pushes.
5. Leaving the shell closes the source, aborts the fetch, and clears the tick.
A failed HTTP response, missing stream body, or streaming failure dispatches an
error event. The shell retains the last event state until a later connection succeeds.
# Architecture map
| File | Responsibility |
|---|---|
| `frontend/src/app/features/home/home.component.ts` | Hosts the shell and starts/stops the authenticated event stream. |
| `frontend/src/app/core/services/authenticated-event-source.service.ts` | Fetch-based authenticated SSE transport with abort and frame parsing. |
| `frontend/src/app/core/services/event-status.store.ts` | Applies event frames and derives the live countdown. |
| `frontend/src/app/features/shell/header/shell-header.component.ts` | Renders event LED, countdown, navigation, and user menu; owns the component-scoped LED shape and state color rules. |
| `frontend/src/styles.css` | Defines the shared theme color tokens consumed by the shell LED. |
| `frontend/src/app/features/shell/tabs/quick-tabs.component.ts` | Renders the main navigation tabs. |
| `tests/frontend/authenticated-event-source.spec.ts` | Verifies authorization headers, SSE frame delivery, and anonymous header omission. |
# Tester flows
## Live event window
1. Configure a future start time and confirm the countdown LED and text appear.
2. Move the start time into the past and the end time into the future; confirm the
LED changes to running and the countdown counts toward the end.
3. Move the end time into the past; confirm `Event ended` and the stopped LED.
4. Remove either setting; confirm the unconfigured LED and empty countdown.
## Navigation and logout
1. Click each quick tab and confirm the matching route and active styling.
2. Open the user menu and click **Logout**.
3. Confirm navigation to `/login` and that the event stream is closed.
# See also
- [Event Window](/guides/event-window.md)
- [System Endpoints](/api/system.md)
- [Frontend Structure](/architecture/frontend-structure.md)
- [Change Password](/guides/change-password.md)