docs: update documentation to OKF v0.1 format
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
---
|
||||
type: database
|
||||
title: Admin Operation Tokens
|
||||
description: Single-use confirmation tokens backing the destructive admin System operations (restore-backup, reset-scores, wipe-challenges).
|
||||
resource: backend/src/database/entities/admin-operation-token.entity.ts
|
||||
tags: [database, admin, system, backup, restore, danger-zone, tokens]
|
||||
timestamp: 2026-07-23T12:04:50Z
|
||||
---
|
||||
|
||||
# Schema
|
||||
|
||||
| Column | Type | Description |
|
||||
|---------------|-----------|----------------------------------------------------------------------------------------------------------|
|
||||
| `id` | TEXT PK | UUIDv4 generated client-side; the primary key. |
|
||||
| `user_id` | TEXT FK | `user.id` of the administrator who issued the token. FK `ON DELETE CASCADE` to `user`. |
|
||||
| `operation` | TEXT | One of `restore-backup`, `reset-scores`, `wipe-challenges` (mirrors `ADMIN_OPERATION_KINDS`). |
|
||||
| `token_hash` | TEXT | Hex-encoded SHA-256 of the raw token. The raw token is returned once and never logged or stored. Unique. |
|
||||
| `issued_at` | TEXT | ISO-8601 timestamp at issuance. |
|
||||
| `expires_at` | TEXT | ISO-8601 timestamp after which the token is invalid (default TTL: `SYSTEM_OP_CONFIRM_TOKEN_TTL_MS`, 5 min). |
|
||||
| `consumed_at` | TEXT null | ISO-8601 timestamp when the token was consumed; null while still valid. |
|
||||
|
||||
# Indexes
|
||||
|
||||
| Index | Purpose |
|
||||
|--------------------------------|--------------------------------------------------------|
|
||||
| `uq_admin_op_token_hash` | `UNIQUE` on `token_hash` — guarantees one-shot use. |
|
||||
| `idx_admin_op_token_user_op` | `(user_id, operation)` — fast per-admin/per-op lookup. |
|
||||
| `idx_admin_op_token_expiry` | `expires_at` — enables the periodic expiry sweep. |
|
||||
|
||||
# Lifecycle
|
||||
|
||||
1. Admin re-authenticates with their current password via
|
||||
`POST /api/v1/admin/system/confirmations`. The backend verifies the
|
||||
password with Argon2id, then `ConfirmationTokenService.issue()`
|
||||
generates a 32-byte base64url token, persists only its SHA-256 hash,
|
||||
and returns the raw token plus its `expiresAt`.
|
||||
2. The client passes the raw token (and the `stagingId` for restores)
|
||||
to the matching destructive endpoint (`/restore/commit`,
|
||||
`/scores/reset`, `/challenges/wipe`).
|
||||
3. `ConfirmationTokenService.consume()` runs the consumption inside a
|
||||
transaction: it looks the token up by hash, validates
|
||||
`user_id` + `operation` (+ `stagingId` for restores), checks
|
||||
`expires_at > now`, and finally performs a conditional update
|
||||
`WHERE consumedAt IS NULL` so only the first concurrent caller
|
||||
succeeds. A second attempt returns `SYSTEM_TOKEN_REUSED`.
|
||||
4. `purgeExpired()` deletes expired rows and consumed rows older than
|
||||
24h.
|
||||
|
||||
# Related
|
||||
|
||||
* Migration: [Admin Operation Tokens Migration](/database/admin-operation-tokens-migration.md)
|
||||
* Service: `backend/src/modules/admin/system/confirmation-token.service.ts`
|
||||
* Error codes: `SYSTEM_TOKEN_INVALID`, `SYSTEM_TOKEN_EXPIRED`,
|
||||
`SYSTEM_TOKEN_REUSED`, `SYSTEM_TOKEN_MISMATCH`
|
||||
* [Admin System API](/api/admin-system.md)
|
||||
Reference in New Issue
Block a user