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:
Siavash Sameni
2026-05-30 18:41:44 +04:00
parent eab1d77582
commit dceaf82934
153 changed files with 6276 additions and 179 deletions

View File

@@ -5,13 +5,16 @@ tags: [api, admin, reference]
# Admin API
> **Last updated:** 2026-05-29aligned with code (see Doc vs Code Audit Report)
> **Last updated:** 2026-05-30break-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