Skip to content

Arylmera/TheGreenGauntlet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

87 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

TheGreenGauntlet

CI Status Node License

🟒 Competition leaderboard for BNP Paribas Fortis DevOps Day β€” tracks account scores across Immersive Labs security challenges, trivia, code duels, and physical games.

Overview

Single-process Node/Express service that proxies the Immersive Labs API, aggregates per-team scores, and serves a React dashboard for live display (TV wall or laptop).

  • Format: per-team leaderboard β€” 30 rows, 1 fresh Immersive Labs account per team.
  • Scoring: Account.points trusted directly. Teams receive new accounts at EVENT_START_AT, so lifetime points = event points by construction.
  • Tie-break: points desc β†’ lastActivityAt asc (earlier finisher wins) β†’ displayName.
  • Event scoping: EVENT_START_AT / EVENT_END_AT drive phase (pre/live/ended) and post-event freeze (stop rebuilds, keep last snapshot). Not used for attempt filtering.
  • Refresh: client polls every 30 s; server caches ~10 s. Snapshot persisted to disk so restarts serve stale instantly.
  • Language: English only (UI copy independent of browser/account locale).

Architecture

Browser (React + Vite)
      β”‚  SSE push + 30 s poll fallback
      β–Ό
Node/Fastify (port 3000)
  β”œβ”€β”€ /api/leaderboard         ← cached aggregate
  β”œβ”€β”€ /api/leaderboard/stream  ← SSE (leaderboard-updated)
  β”œβ”€β”€ /api/announcement        ← public banner read
  β”œβ”€β”€ /api/admin/*             ← cookie-auth (bonuses, announcement, CSV)
  └── syncService              ← OAuth2 + paginated walk
      β–Ό
Immersive Labs API  (https://api.immersivelabs.online)

Persistence: snapshot.json + token.json + bonus.sqlite (named volume)

See:

Tech stack

  • Backend: Node 20+, Fastify, native fetch.
  • Frontend: React + Vite (served as static bundle by the same Node process).
  • Persistence: in-memory snapshot (10 s TTL) backed by snapshot.json + token.json (atomic tmp + rename) plus bonus.sqlite (better-sqlite3, WAL) for admin bonuses + announcement, all on a Docker named volume.
  • Realtime: SSE channel leaderboard-updated; 30 s client poll as fallback.
  • Deploy: single Docker image, port 3000, named volume mounted at /app/data.

Configuration

All config via environment variables. Secrets live only in the backend β€” never shipped to the browser.

Variable Purpose
USE_STUB_UPSTREAM true β†’ serve synthetic data, skip Immersive Labs calls.
IMMERSIVELAB_ACCESS_KEY OAuth2 username for POST /v1/public/tokens.
IMMERSIVELAB_SECRET_TOKEN OAuth2 password.
IMMERSIVELAB_BASE_URL Upstream base URL (default https://api.immersivelabs.online).
EVENT_START_AT ISO 8601 β€” drives phase = "pre" + pre-event gate.
EVENT_END_AT ISO 8601 β€” drives phase = "ended" + post-event freeze.
DATA_DIR Directory for snapshot.json + token.json + bonus.sqlite (default ./data; named volume in prod).
PORT HTTP listen port (default 3000).
SNAPSHOT_TTL_MS Aggregator cache TTL (default 10000).
ADMIN_PASSWORD Required. Shared admin password for /admin.
ADMIN_SESSION_SECRET Required. β‰₯ 32 random chars; HMAC key for the gg_admin signed cookie.
ADMIN_SESSION_TTL_MS Admin cookie lifetime (default 172800000 = 48 h).
BONUS_DB_PATH Override SQLite path (default ${DATA_DIR}/bonus.sqlite).
COOKIE_SECURE Set false when running over plain HTTP (default true).

Local development

# install
npm install

# run (reads .env)
npm run dev          # backend + Vite dev server
npm run build        # static bundle into dist/
npm start            # production single-process

# docker
docker build -t greengauntlet .
docker run -p 3000:3000 -v greengauntlet-data:/app/data --env-file .env greengauntlet

Prior art

A previous per-account leaderboard exists at devops-day-leaderboard (Immersive Lab Leaderboard v2.1). Reusable modules: immersiveLabsAuth.js, immersiveLabsClient.js, syncService.js, SQLite schema. Known gotchas: use ?? (not ||) for totalDuration; tolerate 404 on activity lookup.

Status

v1.1 shipped on develop. Live features:

  • Per-team aggregated leaderboard with SSE push (leaderboard-updated) + 30 s client poll fallback.
  • Stub upstream mode for offline / pre-credential development (USE_STUB_UPSTREAM=true).
  • Admin bonus panel β€” three categories (Mario / Crokinole / Helping), batch commit with per-category negative-guard, per-team active toggle, CSV export. See docs/implementation/admin-bonus-plan.md.
  • Admin announcement banner β€” admin-managed message shown on the public dashboard, max 280 chars, dismissible per client (re-shows when a new message is posted).
  • Mario theme toggle, per-category leaderboard tabs, team search.
  • Persistence: snapshot.json + token.json + bonus.sqlite on a named Docker volume.

See TODO.md for v2 / nice-to-haves.

License

Internal β€” BNP Paribas Fortis DevOps Day.

About

🟒 Competition leaderboard for BNP Paribas Fortis DevOps Day β€” tracking team scores across Immersive Labs security challenges, trivia, code duels, and physical games.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors