audit: 2026-05-30 full-codebase audit — report, issues, docs, runbooks
Full-codebase-audit 2026-05-30 outputs: - Audit report: 09 - Audits/Full Codebase Audit - 2026-05-30.md - 81 issue files ISSUE-055..135 (decisions + 1 skipped no-brainer). - Scanner docs from scratch (was zero): architecture, data model, API ref, payment flow, operations runbook + repo README. - Doc-sync updates across API reference, data models, flows, design system. - Secret Rotation Runbook (08 - Operations) for the exposed credentials. - Reusable workflow guide (07 - Development) + .claude/workflows/full-codebase-audit.js. Issues remain status:open intentionally — the code fixes are uncommitted-then-committed working-tree changes per repo and aren't "resolved" until merged/deployed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,13 +5,16 @@ tags: [api, admin, reference]
|
||||
|
||||
# Admin API
|
||||
|
||||
> **Last updated:** 2026-05-29 — aligned with code (see Doc vs Code Audit Report)
|
||||
> **Last updated:** 2026-05-30 — break-glass endpoints added, scanner/status auth fixed, reload/probe routes now implemented, confirmation threshold history implemented, resolver role added
|
||||
|
||||
There is no single `/api/admin` namespace — admin-only endpoints are scattered across the service routers. This page catalogs them in one place. All require `Bearer JWT` with `req.user.role === 'admin'` unless explicitly noted otherwise. The two enforcement patterns are:
|
||||
|
||||
- Middleware: `authorizeRoles('admin')` after `authenticateToken` (used by the dispute, data-cleanup, blog routers).
|
||||
- Inline check inside the handler: `if (req.user.role !== 'admin') return 403` (used by user, points, payment routes).
|
||||
|
||||
> [!note] Resolver role
|
||||
> The `resolver` role was added (commit `fce8a19`). Resolvers have access to the dispute-triage endpoints (`assign`, `status`, `resolve`, `statistics`) only. All other admin endpoints remain `admin`-only.
|
||||
|
||||
## User management
|
||||
|
||||
See full descriptions in [[User API]].
|
||||
@@ -159,9 +162,14 @@ Router: [`backend/src/services/admin/dataCleanupRoutes.ts`](../../backend/src/se
|
||||
|
||||
### GET /api/admin/scanner/status
|
||||
|
||||
**Description:** Returns the current state of the blockchain scanner / wallet monitor.
|
||||
**Description:** Returns the current state of the AMN Pay Scanner. Proxies to `AMN_SCANNER_URL/scanner/status`.
|
||||
**Auth required:** Bearer JWT (`admin`) — `authenticateToken` + `authorizeRoles('admin')` were added in commit `1d881c5`. The previously documented unauthenticated access gap (ISSUE-006) is closed.
|
||||
|
||||
> **⚠️ SECURITY BUG — NO AUTHENTICATION:** Despite being mounted under `/api/admin/`, this endpoint has **no** `authenticateToken` or `authorizeRoles` guard. Any unauthenticated request can read scanner state.
|
||||
### POST /api/admin/scanner/webhooks/retry
|
||||
|
||||
**Description:** Trigger a retry of failed/pending scanner webhooks.
|
||||
**Auth required:** Bearer JWT (`admin`)
|
||||
**Request body:** `{ intentId?: string }` — omit to retry all pending.
|
||||
|
||||
## Settings
|
||||
|
||||
@@ -174,6 +182,13 @@ Router: [`backend/src/services/admin/dataCleanupRoutes.ts`](../../backend/src/se
|
||||
| `GET /api/admin/settings/aml` | admin | Read current AML settings |
|
||||
| `PATCH /api/admin/settings/aml` | admin | Update AML settings (runtime only — not persisted to disk or DB) |
|
||||
|
||||
**AML providers available:**
|
||||
|
||||
- **Chainalysis** — cloud API provider (requires `CHAINALYSIS_API_KEY`). Enabled via `AML_PROVIDER=chainalysis`.
|
||||
- **OFAC SDN local** — downloads the US Treasury SDN XML list once per 24 hours and checks addresses locally. No API key required. Enabled via `AML_PROVIDER=ofac`. Added in commit `31343d1` (Task #10). List is fetched from `OFAC_SDN_URL` (defaults to `https://www.treasury.gov/ofac/downloads/sdn.xml`).
|
||||
|
||||
The active provider is selected at startup via `AML_PROVIDER`. `PATCH /api/admin/settings/aml` can switch the provider at runtime but the change is not persisted.
|
||||
|
||||
### Confirmation thresholds
|
||||
|
||||
Frontend page exists. Endpoints require admin auth.
|
||||
@@ -182,8 +197,22 @@ Frontend page exists. Endpoints require admin auth.
|
||||
| --- | --- |
|
||||
| `GET /api/admin/settings/confirmation-thresholds` | Get current confirmation thresholds for all chains |
|
||||
| `PATCH /api/admin/settings/confirmation-thresholds/:chainId` | Update threshold for a specific chain |
|
||||
| `GET /api/admin/settings/confirmation-thresholds/history` | Last 50 threshold change events (populated with `changedBy` user email/name) |
|
||||
|
||||
> **Not implemented:** `GET /api/admin/settings/confirmation-thresholds/history` — history endpoint does not exist. `POST /api/admin/rn/networks/reload` and `POST /api/admin/rn/networks/probe/:chainId` do not exist.
|
||||
> **History route:** `GET /api/admin/settings/confirmation-thresholds/history` is now implemented (commit `27fb15a`). It reads from the `ConfigSettingHistory` collection, keyed as `confirmation_threshold:<chainId>`.
|
||||
|
||||
### Break-glass (Trezor bypass)
|
||||
|
||||
Three endpoints manage the break-glass mode, which disables the Trezor safekeeping requirement for escrow release/refund for up to 1 hour. All changes fire a Telegram alert.
|
||||
|
||||
| Endpoint | Action |
|
||||
| --- | --- |
|
||||
| `GET /api/admin/settings/break-glass` | Read current break-glass status (active, expiresAt, activatedBy) |
|
||||
| `POST /api/admin/settings/break-glass` | Activate break-glass for 1 hour |
|
||||
| `DELETE /api/admin/settings/break-glass` | Cancel break-glass before it expires |
|
||||
|
||||
> [!warning] In-memory state
|
||||
> Break-glass state is stored in-memory only (`breakGlassRoutes.ts`). A server restart always clears it, which is intentional. The `isBreakGlassActive()` helper is exported and consumed by the Trezor safekeeping middleware.
|
||||
|
||||
## Payments awaiting confirmation
|
||||
|
||||
@@ -200,6 +229,10 @@ Frontend page exists.
|
||||
| Endpoint | Auth | Action |
|
||||
| --- | --- | --- |
|
||||
| `GET /api/admin/rn/networks` | admin | List all registered RN networks |
|
||||
| `POST /api/admin/rn/networks/reload` | admin | Reload chain + token registries from disk (no restart needed) |
|
||||
| `POST /api/admin/rn/networks/probe/:chainId` | admin | On-demand on-chain probe: RPC reachability, proxy bytecode, dummy-call validity |
|
||||
|
||||
> All three routes are implemented (commit `5681abf`). Previous docs listed reload and probe as not implemented.
|
||||
|
||||
## Blog admin
|
||||
|
||||
|
||||
Reference in New Issue
Block a user