--- type: database title: Auth and Settings Tables description: refresh_token and setting tables — rotating refresh tokens and site configuration. tags: [database, refresh-token, settings, config] timestamp: 2026-07-21T14:18:00Z --- # Tables ## `refresh_token` | Column | Type | Description | |---------------|---------|------------------------------------------------------------------| | `id` | TEXT PK | UUID v4. | | `user_id` | TEXT | FK → `user.id` (indexed, but no DB-level FK cascade is configured). | | `token_hash` | TEXT | SHA-256 of the raw refresh token (unique). | | `issued_at` | TEXT | ISO 8601 timestamp. | | `expires_at` | TEXT | ISO 8601 timestamp; checked on refresh. | | `revoked_at` | TEXT | ISO 8601 timestamp or `NULL` if active. | # Refresh token lifecycle 1. **Issue** — `AuthService.login` and `AuthService.registerFirstAdmin` mint a new token via `crypto.randomBytes(32).toString('base64url')` and store its SHA-256 hash with `expires_at = now + JWT_REFRESH_TTL`. The raw token is set as an HttpOnly `rt` cookie and also returned in the login response body. 2. **Rotate** — `AuthService.refresh` looks up the row by `token_hash`, asserts it isn't revoked/expired, marks `revoked_at = now`, and mints a new token in the same transaction. Each token is single-use. 3. **Logout** — `AuthService.logout` looks up by `token_hash` (from the `rt` cookie) and sets `revoked_at`. Already-revoked or unknown tokens are silently ignored. ## `setting` | Column | Type | Description | |--------|---------|-----------------------------------------------------| | `key` | TEXT PK | Settings key (see `SETTINGS_KEYS` below). | | `value`| TEXT | String value (defaults to empty string). | Read/write access goes through `SettingsService` (`backend/src/modules/settings/settings.module.ts`), which exposes `get(key, fallback?)`, `set(key, value)`, and `getAll()`. # Settings keys Defined in `backend/src/config/env.schema.ts` (`SETTINGS_KEYS`) and seeded by `SeedSystemData1700000000100`: | Key | Default | Consumed by | |-------------------------|------------------------------------------|-------------------------------------------------------------------| | `pageTitle` | `HIPCTF` | `SystemService.bootstrap` → `pageTitle` | | `logo` | `""` | `SystemService.bootstrap` → `logo` | | `welcomeMarkdown` | `"# Welcome\n\nCreate the first admin..."` | `SystemService.bootstrap` → `welcomeMarkdown` | | `themeKey` | `classic` | `SystemService.bootstrap` → `theme` (overridden via `ThemeLoaderService`) | | `defaultChallengeIp` | `127.0.0.1` | `SystemService.bootstrap` → `defaultChallengeIp` | | `registrationsEnabled` | `false` | `SystemService.bootstrap` → `registrationsEnabled` | | `eventStartUtc` | `now + 60s` (ISO) | `EventStatusService.getStatus` | | `eventEndUtc` | `now + 7d` (ISO) | `EventStatusService.getStatus` | # See also - [Database Schema Overview](/database/schema.md) - [User Table](/database/users.md) - [System Endpoints](/api/system.md)