Files
HIPCTF2/docs/api/system.md
T
2026-07-22 13:41:05 +00:00

5.8 KiB

type, title, description, tags, timestamp
type title description tags timestamp
api System Endpoints Bootstrap payload, public event status, public/authenticated SSE streams, and public event-window timestamps.
api
system
bootstrap
event
sse
settings
2026-07-22T13:40:00Z

Endpoints

Method Path Auth Source
GET /api/v1/bootstrap Public backend/src/modules/system/system.controller.ts
GET /api/v1/event/status Public Same.
GET /api/v1/event/stream Public (SSE) Same.
GET /api/v1/settings/event Public Same.
GET /api/v1/events/status Authenticated (SSE) Same.
GET /api/v1/scoreboard/stream Public (SSE) Same.

Path note: the authenticated status stream is mounted at the plural /api/v1/events/status so it can be distinguished from the legacy public /api/v1/event/status snapshot endpoint.

GET /api/v1/bootstrap

Built by SystemService.bootstrap(). Public payload consumed by the SPA's BootstrapService:

{
  "initialized": true,
  "pageTitle": "HIPCTF",
  "logo": "",
  "welcomeMarkdown": "# Welcome\n\n...",
  "theme": { "id": "classic", "tokens": { "...": "..." } },
  "defaultChallengeIp": "127.0.0.1",
  "registrationsEnabled": false,
  "passwordPolicy": {
    "minLength": 12,
    "requireMixed": true,
    "description": "At least 12 characters with upper, lower, digit and symbol"
  }
}
  • initialized is true iff at least one admin user exists.
  • theme is the resolved Theme (one of the 10 canonical themes; see Theming).
  • registrationsEnabled is read from the setting table (SETTINGS_KEYS.REGISTRATIONS_ENABLED) and gates the new public register endpoint (see Auth Endpoints).
  • passwordPolicy is derived from PASSWORD_MIN_LENGTH / PASSWORD_REQUIRE_MIXED env vars (see Change Password Guide).
  • The frontend BootstrapService caches the initial bootstrap request through load()/ready(). Its refresh() method fetches the payload again, updates signals, and reapplies the theme; /admin/general calls it after a successful settings update.

GET /api/v1/event/status (legacy public snapshot)

Returns the current event window computed by EventStatusService.getStatus():

{ "state": "Running", "countdownMs": 12345, "startUtc": "...", "endUtc": "...", "serverNowUtc": "..." }

status is Stopped while now < eventStartUtc (countdown), Running between start and end, and Stopped once now >= eventEndUtc. This endpoint is preserved for backward compatibility — new consumers should use getState() (see below).

GET /api/v1/settings/event (public timestamps)

Returns the raw UTC event-window timestamps without computing state. Useful for the SPA when only the window endpoints are needed:

{ "eventStartUtc": "2026-07-21T12:00:00.000Z", "eventEndUtc": "2026-07-28T12:00:00.000Z" }

A null value for either field means that the underlying setting row is missing or empty; in that case EventStatusService.getState() returns the unconfigured state.

GET /api/v1/events/status (authenticated SSE)

Authenticated Server-Sent Events stream that pushes the full EventStatePayload whenever it changes. Protected by the global JwtAuthGuard — unauthenticated clients receive 401 before any frame is sent.

Each frame:

{
  "state": "countdown" | "running" | "stopped" | "unconfigured",
  "serverNowUtc": "2026-07-21T12:00:00.000Z",
  "eventStartUtc": "2026-07-21T12:00:00.000Z" | null,
  "eventEndUtc":   "2026-07-28T12:00:00.000Z" | null,
  "secondsToStart": 3600,
  "secondsToEnd":   604800
}
  • state transitions:
    • unconfiguredeventStartUtc/eventEndUtc settings are missing or unparseable.
    • countdownnow < eventStartUtc.
    • runningstart <= now <= end.
    • stoppednow > eventEndUtc.
  • The stream emits:
    1. An initial frame on connect (defer(getState())).
    2. A 60-second tick frame so the SPA can update even if no admin cron publishes through the hub.
    3. Any frame pushed via SseHubService.publish().
    • Consecutive identical payloads are suppressed via distinctUntilChanged(JSON.stringify).

See backend/src/common/services/event-status.service.ts for the authoritative state machine; see Event Window Guide for the full diagram and the SPA wiring. The authenticated browser consumer uses the fetch-based transport in frontend/src/app/core/services/authenticated-event-source.service.ts so it can send the JWT Authorization header; native EventSource cannot set that header.

GET /api/v1/event/stream (public SSE, legacy)

Public, flattened event stream that emits the legacy payload shape (status, countdownMs, startUtc, endUtc, serverNowUtc) on a 1-second tick and on hub pushes. Preserved for backward compatibility with the original landing page status badge.

GET /api/v1/scoreboard/stream

Public SSE stream that pushes a flattened solve payload whenever a new solve is published (backend/src/common/services/sse-hub.service.ts).

See also