AI Implementation feature(820): Project Scaffold and Platform Foundations (#1)

This commit was merged in pull request #1.
This commit is contained in:
2026-07-21 14:23:53 +00:00
parent e55c9cda56
commit 03bcb6b156
131 changed files with 23657 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
---
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)