Scaffold HIPCTF platform (NestJS + Angular)

- Backend: NestJS 10 + TypeORM (better-sqlite3) feature-modular layout.
  - Entities: user, setting, category, challenge, challenge_file, solve,
    refresh_token, blog_post. Auto-run migrations + idempotent 6-system-
    category seed on startup.
  - Argon2id password hashing with policy check; JWT access + rotating
    refresh tokens (HttpOnly cookie); CSRF middleware (SameSite + custom
    X-CSRF-Token header); global JWT auth guard with @Public() opt-out;
    per-IP login backoff + per-IP registration rate limit.
  - Endpoints: auth (login/refresh/logout/csrf), users (first-admin
    registration), system (bootstrap/event status/SSE), admin (guarded
    user CRUD with last-admin invariant), frontend module (uploads +
    SPA fallback).
  - Security: helmet+CSP+HSTS-gated-by-TLS, CORS allowlist, structured
    global exception filter, Zod request validation pipes, OpenAPI 3.1
    served at /api/docs and /api/docs-json, 10 canonical themes under
    backend/themes/.
- Frontend: Angular 17 standalone components, lazy-loaded feature routes,
  signals, functional HttpInterceptorFn (csrf + auth), functional
  CanActivateFn auth guard, HttpOnly-cookie-based auth service.
- Tests: Jest + supertest, 46 tests across 13 suites covering
  migrations, env schema, theme loader, event status, login backoff,
  registration rate limit, ApiError shape, bootstrap integration,
  auth refresh rotation, admin guard, last-admin invariant, SSE flat
  payloads. Single-command runner: `npm test`.
This commit is contained in:
OpenVelo Agent
2026-07-21 13:25:49 +00:00
parent e55c9cda56
commit af3c24275d
112 changed files with 21931 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
{
"id": "classic",
"name": "Classic",
"tokens": {
"primary": "#3b82f6",
"secondary": "#64748b",
"accent": "#f59e0b",
"surface": "#ffffff",
"text": "#0f172a",
"success": "#10b981",
"warning": "#f59e0b",
"danger": "#ef4444",
"fontFamily": "system-ui, sans-serif",
"radii": { "sm": "4px", "md": "8px", "lg": "16px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "midnight",
"name": "Midnight",
"tokens": {
"primary": "#6366f1",
"secondary": "#1e293b",
"accent": "#22d3ee",
"surface": "#0f172a",
"text": "#e2e8f0",
"success": "#34d399",
"warning": "#fbbf24",
"danger": "#f87171",
"fontFamily": "system-ui, sans-serif",
"radii": { "sm": "4px", "md": "8px", "lg": "16px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "sunset",
"name": "Sunset",
"tokens": {
"primary": "#f97316",
"secondary": "#fb7185",
"accent": "#facc15",
"surface": "#fff7ed",
"text": "#431407",
"success": "#84cc16",
"warning": "#f59e0b",
"danger": "#dc2626",
"fontFamily": "Georgia, serif",
"radii": { "sm": "6px", "md": "12px", "lg": "24px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "forest",
"name": "Forest",
"tokens": {
"primary": "#16a34a",
"secondary": "#65a30d",
"accent": "#ca8a04",
"surface": "#f0fdf4",
"text": "#14532d",
"success": "#15803d",
"warning": "#ca8a04",
"danger": "#b91c1c",
"fontFamily": "system-ui, sans-serif",
"radii": { "sm": "4px", "md": "8px", "lg": "12px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "cyber",
"name": "Cyber",
"tokens": {
"primary": "#00ffd5",
"secondary": "#ff00aa",
"accent": "#ffee00",
"surface": "#000000",
"text": "#00ffd5",
"success": "#00ff88",
"warning": "#ffee00",
"danger": "#ff0066",
"fontFamily": "Courier New, monospace",
"radii": { "sm": "0", "md": "0", "lg": "0" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "paper",
"name": "Paper",
"tokens": {
"primary": "#1f2937",
"secondary": "#6b7280",
"accent": "#0ea5e9",
"surface": "#fafaf9",
"text": "#1c1917",
"success": "#059669",
"warning": "#d97706",
"danger": "#b91c1c",
"fontFamily": "Georgia, serif",
"radii": { "sm": "2px", "md": "4px", "lg": "8px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "crimson",
"name": "Crimson",
"tokens": {
"primary": "#dc2626",
"secondary": "#991b1b",
"accent": "#fbbf24",
"surface": "#1f1f1f",
"text": "#fef2f2",
"success": "#22c55e",
"warning": "#fbbf24",
"danger": "#ef4444",
"fontFamily": "system-ui, sans-serif",
"radii": { "sm": "4px", "md": "8px", "lg": "12px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "ocean",
"name": "Ocean",
"tokens": {
"primary": "#0ea5e9",
"secondary": "#06b6d4",
"accent": "#14b8a6",
"surface": "#f0f9ff",
"text": "#0c4a6e",
"success": "#10b981",
"warning": "#f59e0b",
"danger": "#ef4444",
"fontFamily": "system-ui, sans-serif",
"radii": { "sm": "8px", "md": "16px", "lg": "24px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "neon",
"name": "Neon",
"tokens": {
"primary": "#a855f7",
"secondary": "#ec4899",
"accent": "#22d3ee",
"surface": "#0a0a0a",
"text": "#f5f3ff",
"success": "#4ade80",
"warning": "#fbbf24",
"danger": "#fb7185",
"fontFamily": "system-ui, sans-serif",
"radii": { "sm": "4px", "md": "12px", "lg": "20px" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "monochrome",
"name": "Monochrome",
"tokens": {
"primary": "#000000",
"secondary": "#525252",
"accent": "#a3a3a3",
"surface": "#ffffff",
"text": "#0a0a0a",
"success": "#404040",
"warning": "#737373",
"danger": "#171717",
"fontFamily": "system-ui, sans-serif",
"radii": { "sm": "0", "md": "0", "lg": "0" },
"spacingScale": [4, 8, 12, 16, 24, 32, 48]
}
}