Admin Panel ↔ Payment Manager¶
Документ описывает, как Admin Panel (SvelteKit) интегрирована с Payment Manager: какие endpoint'ы вызывает, какой service key использует и почему прямой доступ к TigerBeetle разрешён только в read-only режиме.
1. Назначение интеграции¶
Admin Panel — внутренний SvelteKit-сервис для операторов (бухгалтеры, support, compliance). Через него выполняются:
- Финансовые операции (TOPUP, withdrawal equity close, float reload, бонусы, корректировки, выплаты merchant/agent settlement) — все идут через канал
ADMIN(operationType: ADMIN_TRANSFER). - Просмотр состояния системы — балансы счетов, история транзакций, статус intent'ов, очередь MANUAL_REVIEW.
- Резолв «зависших» intent'ов — через
POST /admin/intents/:id/resolve(см. ../api/admin.md). - Управление настройками — fee rules, лимиты, уровень логирования, health-check.
Admin Panel взаимодействует с PM двумя способами:
| Способ | Что делает | Где |
|---|---|---|
| HTTP вызовы в PM с HMAC | Все мутирующие операции (write) + получение балансов и истории | POST /intents, POST /admin/*, GET /accounts/balance, GET /history |
| Прямой TigerBeetle SDK (read-only) | Быстрый lookup аккаунтов, query балансов и transfer'ов для построения дашбордов | TigerBeetle cluster |
2. NO-GO — главное правило интеграции¶
Admin Panel НИКОГДА не делает write в TigerBeetle напрямую.
Все финансовые мутации (создание/закрытие transfer'ов, изменение состояния аккаунтов) проходят исключительно через POST /intents в Payment Manager с HMAC-подписью. Это гарантирует:
- единый аудит-трейл (
tx_history,event_log, intent-статусы); - проверку через rule-engine (комиссии, лимиты, разрешения);
- срабатывание уведомлений и обновление балансов в одной транзакции;
- невозможность «теневых» проводок мимо saga'и и outbox'а.
Прямой TigerBeetle SDK в Admin Panel разрешён только для чтения: lookupAccounts, lookupTransfers, getAccountBalances, getAccountTransfers, queryAccounts, queryTransfers. Любая попытка вызвать createAccounts / createTransfers из Admin Panel — нарушение архитектуры (см. корневой CLAUDE.md, раздел «Доступ к TigerBeetle»).
Создание новых TB-аккаунтов также не делается напрямую — для этого есть POST /accounts с service key admin-tool (см. ниже).
3. Service keys¶
Admin-инфраструктура использует два разных service key — у них разные права и разные правила формирования X-User-Id:
| Service key | Назначение | X-User-Id |
|---|---|---|
admin-panel |
Финансовые операции через POST /intents (ADMIN_TRANSFER) |
0 (системный, реального пользователя нет) |
admin-tool |
Создание TB-аккаунтов (POST /accounts для merchant/agent), force-resolve MANUAL_REVIEW |
userId целевой сущности |
Подробное описание разрешений каждого ключа, regex-паттернов и allowedOperationTypes — в ../reference/passport/06-service-keys.md.
Канонический seed-источник прав — drizzle/seed.ts. Секреты обоих ключей берутся из env-переменной SERVICE_SECRETS (JSON-объект), никогда не хранятся в БД.
HMAC-схема для Admin Panel идентична общей схеме PM:
X-Service-Id: admin-panel
X-Timestamp: <unix seconds>
X-Signature: hex(hmac_sha256(stringToSign, SECRET))
X-User-Id: 0
stringToSign = {timestamp}\n{METHOD}\n{PATH}\n{sha256hex(rawBody)}. Подпись формируется на сервере SvelteKit (server route'ы) — секрет никогда не должен попадать в браузер. Подробнее об HMAC и открытом вопросе про POST /admin/* см. ../api/auth.md.
4. Список admin-операций¶
Полный перечень endpoint'ов с request/response-схемами, error-кодами и примерами:
POST /intents(operationType=ADMIN_TRANSFER) — универсальная финансовая операция: см. ../api/intents.md и ../reference/passport/02-channels.md (каналADMIN).POST /admin/intents/:id/resolve— force-resolve intent в MANUAL_REVIEW (толькоadmin-tool).POST /accounts— создание merchant/agent кошельков (primary + settlement сразу) с service keyadmin-tool. Идемпотентно: повторный вызов вернёт200с теми жеtbAccountId.GET /admin/fee-rules,POST /admin/fee-rules— управление fee rules.GET /admin/health— расширенный health (TB, PG, Redis, очереди).POST /admin/debug-level— динамическое изменение уровня логирования.GET /accounts/balance?account=<name>,GET /history?...— чтение балансов и истории (через PM, не напрямую в TB).
Все эти эндпоинты, их параметры, права доступа и коды ошибок описаны в ../api/admin.md.
Типовые финансовые сценарии (TOPUP, withdrawal equity close, float reload, бонусы, payout merchant/agent settlement) и соответствующие пары fromAccountName / toAccountName — см. в ../api/intents.md (раздел «ADMIN_TRANSFER» / channel ADMIN).
Матрица прав по entityType для POST /accounts¶
entityType |
Кто вызывает | Что создаётся |
|---|---|---|
"user" |
auth-center (или admin-panel для ручного recovery) |
USER_WALLET |
"merchant" |
admin-tool |
MERCHANT_WALLET + MERCHANT_SETTLEMENT |
"agent" |
admin-tool |
AGENT_WALLET + AGENT_SETTLEMENT |
Settlement-аккаунты (*.settlement.THB) создаются только через POST /accounts (одной транзакцией с primary) и не могут использоваться как fromAccountName / toAccountName в ADMIN_TRANSFER — их пополнение происходит исключительно через fee-rule expression'ы. Для выплаты со settlement используется отдельный ADMIN_TRANSFER из *.settlement.THB в *.THB (primary).
5. Прямой TigerBeetle SDK (read-only)¶
Admin Panel держит собственный TB-клиент (отдельный от PM-кластера соединений) и использует его только для чтения. Это оправдано, потому что:
- дашборды и отчёты делают тяжёлые batch-lookup'ы — гонять их через REST-прокси PM неэффективно;
- TB SDK сам по себе read-safe (createAccounts/createTransfers требуют сознательного вызова, мы их просто никогда не пишем в коде Admin Panel);
- read-only операции не нарушают инвариант
transit.balance = 0и не требуют HMAC-аудита.
Разрешённые TB-методы из Admin Panel:
| Метод | Зачем |
|---|---|
lookupAccounts(ids[]) |
Получить состояние конкретных аккаунтов по их детерминированным id |
lookupTransfers(ids[]) |
Резолв transfer-id'ов в детали (для drill-down из tx_history) |
getAccountBalances(filter) |
Исторический временной ряд балансов (графики) |
getAccountTransfers(filter) |
Постраничный список transfer'ов аккаунта |
queryAccounts(filter) |
Поиск аккаунтов по ledger / code / user_data |
queryTransfers(filter) |
Поиск transfer'ов по code / user_data / временному окну |
Балансы для пользовательских экранов (не дашборд оператора) Auth Center по-прежнему берёт через nginx→PM-прокси (
GET /api/pm/accounts/balance). Admin Panel — единственный сервис кроме PM, которому позволен прямой TB-клиент, и только read-only.
6. Идемпотентность и ретраи¶
Все POST /intents (включая ADMIN_TRANSFER) должны иметь уникальный idempotencyKey (UUIDv4). Если SvelteKit ретраит запрос из-за сетевой ошибки, он использует тот же idempotencyKey — PM вернёт оригинальный результат без повторного transfer'а.
import { randomUUID } from 'node:crypto'
const idempotencyKey = randomUUID() // один раз на инициирование операции, не на ретрай
Подробности про идемпотентность — в ../api/intents.md.
7. Архитектурные инварианты, которые держит Admin Panel¶
При работе через Admin Panel оператор не должен иметь возможности нарушить ключевые инварианты PM:
transit.balance = 0— Admin Panel в принципе не работает с TRANSIT-аккаунтами; каналADMINиспользует прямойfrom → totransfer без transit'а, поэтому инвариант сохраняется автоматически.debits_must_not_exceed_creditsна USER_WALLET / MERCHANT_WALLET / AGENT_WALLET — попытка списать больше остатка вернёт409от TigerBeetle (см. ../api/errors.md).- Аудит — каждый
ADMIN_TRANSFERпишется вtx_historyсcommentиmetadata.operatorId. Оператор обязан заполнятьcommentчеловекочитаемой ссылкой на первоисточник (ref банковской выписки, ID тикета, ID intent'а). - HMAC-секреты
admin-panel/admin-toolне покидают сервер — все подписи формируются в SvelteKit server route'ах; браузерный код вызывает только публичный SvelteKit API.
8. Заметка о миграции документации¶
Старый файл
docs/ADMIN_PANEL.md(в корнеdocs/) будет удалён в Phase 9 документационного overhaul'а. Вся актуальная информация по интеграции Admin Panel ↔ PM теперь распределена так:
- этот файл — обзор интеграции, NO-GO правила, service keys;
- ../api/admin.md — endpoint'ы
POST /admin/*;- ../api/intents.md —
ADMIN_TRANSFERи сценарии;- ../reference/passport/02-channels.md — канал
ADMIN;- ../reference/passport/06-service-keys.md — права
admin-panelиadmin-tool;- ../api/auth.md — HMAC-схема и open question по защите
POST /admin/*.
При расхождениях между старым docs/ADMIN_PANEL.md и файлами в docs/dev/ приоритет имеют документы в docs/dev/.
См. также
- ../api/intents.md —
POST /intentsи каналADMIN - ../api/admin.md — endpoint'ы админ-операций
- ../api/auth.md — HMAC-схема, open question
- ../reference/passport/02-channels.md — каналы (включая
ADMIN) - ../reference/passport/06-service-keys.md — service keys
- drizzle/seed.ts — канонический seed прав
admin-panel/admin-tool