docs: reorganize system knowledge by domain
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# Внешние интеграции
|
||||
|
||||
WealthLedger получает личные инвестиционные сведения и публичные данные
|
||||
из разных источников. У каждого своя ответственность и поведение при отказе;
|
||||
политика запросов T-Bank не распространяется автоматически на остальные.
|
||||
|
||||
| Источник | Для чего используется | Граница обращения |
|
||||
| --- | --- | --- |
|
||||
| [T-Bank Invest API](tbank.md) | Счета, позиции, деньги, операции, инструменты и рыночные данные | Backend, gRPC over TLS с token пользователя |
|
||||
| [MOEX ISS](moex.md) | Эффективная доходность и календарные события облигаций | Backend, публичные HTTPS-запросы JSON |
|
||||
| [Реестр НКР](nkr.md) | Кредитный рейтинг конкретного выпуска | Backend, публичная HTML-таблица |
|
||||
| [T-Bank Brands CDN](tbank.md#публичные-логотипы) | Изображения инструментов | Браузер, публичные HTTPS-запросы изображений |
|
||||
|
||||
Внешние источники и приложения показаны в [контексте системы](../architecture/context.md)
|
||||
и [Container](../architecture/containers.md). Публичные параметры выпуска
|
||||
не подтверждают владение бумагой или личное зачисление: эти сведения
|
||||
относятся к текущему брокерскому подключению и исполненным операциям.
|
||||
@@ -0,0 +1,53 @@
|
||||
# Интеграция с MOEX ISS
|
||||
|
||||
MOEX ISS дополняет данные T-Bank публичной информацией об облигациях.
|
||||
Backend получает её по HTTPS в JSON с `iss.moex.com`; запросы содержат
|
||||
идентификаторы выпуска, без token T-Bank и идентификатора брокерского счёта.
|
||||
MOEX не определяет доступ пользователя к инвестициям и не подтверждает
|
||||
личное получение выплаты.
|
||||
|
||||
## Данные и сопоставление выпуска
|
||||
|
||||
| Данные MOEX | Использование в WealthLedger |
|
||||
| --- | --- |
|
||||
| Эффективная доходность, цена её расчёта, целевая дата и время торгов | Рыночный показатель на [странице облигации](../domains/instruments/bonds.md#содержание) |
|
||||
| Купоны и оферты из календаря `bondization` | [Будущие события](../domains/income/upcoming-events.md) по текущим позициям |
|
||||
| Дата погашения, номинал и валюта из описания выпуска | Прогноз полного погашения в том же разделе событий |
|
||||
|
||||
Для доходности backend сопоставляет SECID, ISIN и BOARDID с идентификаторами
|
||||
облигации T-Bank. Совпадения названия недостаточно. Значение сопровождается
|
||||
собственной ценой расчёта и временем MOEX; оно может отличаться от котировки
|
||||
T-Bank и не является личной доходностью инвестора.
|
||||
|
||||
Для календаря используется SECID, разрешённый из тикера позиции или её
|
||||
метаданных. Backend читает страницы календаря, затем применяет выбранный
|
||||
период и текущее количество бумаг. Смысл прогнозных сумм и ограничения
|
||||
оферты определяет [область будущих выплат](../domains/income/upcoming-events.md).
|
||||
Купонный календарь непосредственно на странице облигации получает данные
|
||||
через T-Bank `GetBondCoupons`; эти два пользовательских представления
|
||||
не следует считать одним источником календаря.
|
||||
|
||||
## Недоступность и свежесть
|
||||
|
||||
HTTP-запрос ограничен таймаутом. Сеть, неуспешный HTTP-ответ, кроме `404`,
|
||||
или некорректная структура ответа приводят к `MOEX_UNAVAILABLE`.
|
||||
`404` и отсутствие запрошенного блока означают отсутствие доступных данных;
|
||||
для доходности неподходящий выпуск или неполные обязательные значения
|
||||
также дают отсутствие показателя. Это отличается от отказа источника.
|
||||
|
||||
Последствие ошибки зависит от потребителя:
|
||||
|
||||
- Метрики облигации отмечают недоступность доходности, сохраняя доступные
|
||||
показатели других источников.
|
||||
- Расчёт будущих событий завершается ошибкой `503`, если необходимый календарь
|
||||
недоступен; частичный список не выдаётся за полный.
|
||||
|
||||
Клиент MOEX не использует очередь, повторы и лимитер gRPC T-Bank и не хранит
|
||||
собственный кэш. Повторное использование собранных метрик принадлежит
|
||||
[странице облигации](../domains/instruments/bonds.md#получение-данных-и-восстановление).
|
||||
Наличие успешного HTTP-ответа не гарантирует котировку без задержки.
|
||||
|
||||
Условия обработки источника в прогнозе закреплены в
|
||||
[спецификации будущих событий](../../specs/openspec/specs/brokerage-account-upcoming-events/spec.md#requirement-upcoming-events-use-complete-source-results).
|
||||
Точный механизм транспорта, разбора и сопоставления реализован в
|
||||
[клиенте MOEX](../../backend/src/tbank/moex.client.ts).
|
||||
@@ -0,0 +1,45 @@
|
||||
# Интеграция с реестром НКР
|
||||
|
||||
НКР предоставляет кредитный рейтинг конкретного выпуска облигаций.
|
||||
Backend загружает общий публичный [реестр выпусков](https://ratings.ru/ratings/issues/)
|
||||
по HTTPS и ищет запись локально по точному ISIN. Ни token T-Bank,
|
||||
ни сведения о пользователе или его счёте в запрос реестра не передаются.
|
||||
|
||||
## Значение и выбор записи
|
||||
|
||||
Рейтинг загружается для показателей открытой [страницы облигации](../domains/instruments/bonds.md#содержание),
|
||||
а не для каждого результата поиска инструментов. Выбирается последнее
|
||||
рейтинговое действие для ISIN. Отозванный рейтинг сохраняется как отдельное
|
||||
состояние без действующего значения; противоречивые записи с одной датой
|
||||
не разрешаются произвольным выбором.
|
||||
|
||||
Результат содержит агентство, значение или отзыв, дату рейтингового действия,
|
||||
время получения реестра и ссылку на выпуск. Дата действия и время загрузки
|
||||
имеют разный смысл: обращение к кэшу не делает сам рейтинг новее.
|
||||
|
||||
Отсутствие записи в успешно прочитанном реестре означает, что этот источник
|
||||
не дал рейтинга выпуска. Оно не доказывает отсутствия рейтингов других
|
||||
агентств. Рейтинг эмитента и уровень риска T-Bank не подставляются вместо
|
||||
рейтинга выпуска. Причины выбора, альтернативы и ограничения распространения
|
||||
данных сохранены в [ADR 013](../adr/013-nkr-bond-credit-ratings.md).
|
||||
|
||||
## Загрузка, кэш и отказ источника
|
||||
|
||||
Интеграция читает публичную HTML-таблицу. Штатный открытый API для этой таблицы
|
||||
не подтверждён; текущий механизм зависит от её структуры, формата рейтинга,
|
||||
ISIN, даты и ссылки на выпуск. Изменение таблицы, противоречивые записи,
|
||||
пустой распознанный реестр или ошибка загрузки означают `NCR_UNAVAILABLE`,
|
||||
а не успешный ответ «рейтинга нет».
|
||||
|
||||
Общий реестр сохраняется в памяти экземпляра backend на шесть часов.
|
||||
Одновременные обращения к разным выпускам используют одну незавершённую загрузку.
|
||||
После ошибки новая загрузка ограничена минутным интервалом; внутри одного
|
||||
HTTP-запроса повторных попыток нет. Обновление запускается следующим обращением
|
||||
после истечения кэша, без фонового задания. Точный механизм и сроки принадлежат
|
||||
[клиенту НКР](../../backend/src/tbank/ncr-ratings.client.ts).
|
||||
|
||||
При отказе реестра показатели облигации отмечают недоступность рейтинга,
|
||||
сохраняя остальные доступные показатели. Готовый ответ метрик имеет
|
||||
[собственный кэш](../domains/instruments/bonds.md#получение-данных-и-восстановление),
|
||||
отдельный от общего публичного реестра. Такая обработка не обещает непрерывной
|
||||
доступности источника или наличия рейтинга у каждого выпуска.
|
||||
@@ -0,0 +1,149 @@
|
||||
# Интеграция с T-Bank Invest
|
||||
|
||||
T-Bank — источник доступных пользователю инвестиционных счетов, текущих
|
||||
позиций и денег, исполненных операций и рыночных сведений об инструментах.
|
||||
WealthLedger обращается к Invest API на сервере по gRPC over TLS и преобразует
|
||||
ответы в собственный HTTP API. Изображения логотипов загружаются браузером
|
||||
отдельно из публичного CDN; это не доступ к личным брокерским данным.
|
||||
|
||||
## Данные и ответственность
|
||||
|
||||
| Категория | Для чего используется |
|
||||
| --- | --- |
|
||||
| Открытые счета | Определить доступный состав счетов и проверить доступ к конкретному счёту |
|
||||
| Портфель и денежные остатки | Показать текущий состав инвестиций и итоги по исходным валютам |
|
||||
| Исполненные операции | Построить журнал и выделить полученные купоны и дивиденды |
|
||||
| Инструменты и рынок | Имена, идентификаторы, цены, свечи, параметры акций и облигаций |
|
||||
| Купоны и дивиденды | Построить будущие события по текущим позициям и календарь инструмента |
|
||||
|
||||
T-Bank определяет исходные данные и права token. Backend проверяет локальную
|
||||
сессию, выбирает подключение её пользователя и устанавливает доступ к счёту.
|
||||
Наличие идентификатора счёта в URL этого доступа не подтверждает.
|
||||
|
||||
[MOEX](moex.md) и [НКР](nkr.md) дополняют публичные сведения об облигациях; они не заменяют
|
||||
брокера как источник личных позиций и исполненных выплат. Границы источников
|
||||
показаны в [контексте](../architecture/context.md), смысл дополнений — в
|
||||
[описании облигаций](../domains/instruments/bonds.md).
|
||||
|
||||
## Публичные логотипы
|
||||
|
||||
T-Bank Brands CDN — отдельная публичная граница для изображений.
|
||||
Backend передаёт имя файла `logoName` из метаданных инструмента; frontend
|
||||
строит URL на `invest-brands.cdn-tinkoff.ru` и загружает изображение браузером.
|
||||
Эти запросы не используют HTTP-клиент приложения, его Bearer token
|
||||
или token Invest API. Лимитер и повторы серверных gRPC-вызовов к ним не относятся.
|
||||
|
||||
Логотипы используются в портфеле, операциях, будущих событиях, поиске и
|
||||
страницах инструментов. Отсутствующее имя или ошибка изображения оставляют
|
||||
буквенную заглушку и не меняют финансовые значения. Правило построения URL
|
||||
принадлежит [форматированию frontend](../../frontend/src/shared/lib/display.ts).
|
||||
|
||||
## Проверка и сохранение подключения
|
||||
|
||||
Авторизованный пользователь управляет одним подключением в настройках.
|
||||
Интерфейс просит read-only T-Bank Invest token: он вводится в поле пароля
|
||||
и отправляется backend. API возвращает только состояние подключения и время
|
||||
его сохранения, не token. Успешное сохранение очищает поле, ошибка оставляет
|
||||
введённое значение для исправления. Удаление требует подтверждения в форме;
|
||||
во время изменения действия секции заблокированы.
|
||||
|
||||
Схема показывает динамический сценарий создания или замены подключения.
|
||||
SQLite — локальное хранилище backend, а не отдельный сетевой участник.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as Пользователь
|
||||
participant F as React SPA
|
||||
participant B as Backend API
|
||||
participant T as T-Bank Invest API
|
||||
participant D as Локальная SQLite
|
||||
U->>F: Вводит token и сохраняет подключение
|
||||
F->>B: PUT connection с Bearer и token
|
||||
B->>T: GetAccounts OPEN по gRPC over TLS
|
||||
alt Проверка успешна, в том числе при пустом списке счетов
|
||||
T-->>B: Доступные открытые счета
|
||||
B->>D: Создать или заменить шифротекст AES-256-GCM
|
||||
B-->>F: Подключено и время сохранения
|
||||
F->>F: Обновить статус и сбросить финансовые выборки
|
||||
F-->>U: Показать подтверждённое подключение
|
||||
else Token отклонён или источник недоступен
|
||||
T-->>B: Ошибка проверки
|
||||
B-->>F: INVALID_TBANK_TOKEN или TBANK_UNAVAILABLE
|
||||
F-->>U: Локальная ошибка, прежнее подключение сохранено
|
||||
end
|
||||
```
|
||||
|
||||
Перед проверкой backend удаляет внешние пробелы token и отклоняет пустое
|
||||
значение. Успешный пустой список счетов подтверждает token: наличие позиций
|
||||
не является условием подключения. Ошибка проверки не заменяет уже сохранённое
|
||||
подключение. Сетевой вызов T-Bank и запись SQLite выполняются последовательно,
|
||||
но не образуют общую транзакцию между системами.
|
||||
|
||||
## Состояние и ошибки
|
||||
|
||||
Состояние без подключения содержит `connected: false` и `connectedAt: null`.
|
||||
После создания или замены `connectedAt` содержит время успешного сохранения
|
||||
в RFC 3339 UTC. Это время подключения, а не отметка свежести портфеля.
|
||||
Чтение статуса показывает сохранённое состояние; оно не выполняет заново
|
||||
проверку token у брокера. Если статус загрузить не удалось, интерфейс
|
||||
показывает ошибку с повтором, а не форму с предполагаемым отсутствием
|
||||
подключения.
|
||||
|
||||
`INVALID_TBANK_TOKEN` означает отказ внешней аутентификации или прав доступа.
|
||||
`TBANK_UNAVAILABLE` сообщает о временной или иной upstream-ошибке, включая
|
||||
исчерпание очереди. Ответы и ошибки не содержат token. Удаление подключения
|
||||
идемпотентно: удаляется локальный секрет и прекращается его использование
|
||||
для последующих запросов. Оно не описывает отзыв token на стороне T-Bank.
|
||||
|
||||
Согласованное поведение сохранено в workspace-спецификации
|
||||
[T-Bank connection](../../specs/openspec/specs/tbank-connection/spec.md).
|
||||
Точные endpoints и формы ответов определяет backend OpenAPI;
|
||||
[HTTP API](../architecture/http-api.md) описывает общую границу.
|
||||
|
||||
## Граница финансового кэша
|
||||
|
||||
Успешное создание, замена или удаление подключения меняет границу повторного
|
||||
использования финансовых данных. Это относится и к сохранению того же самого
|
||||
token: предыдущее подключение не становится источником данных нового.
|
||||
Неуспешная операция сохраняет прежнее подключение и его доступные данные.
|
||||
Механизм generation, поздние ответы и сброс клиентских выборок объясняет
|
||||
[свежесть данных](../architecture/cross-cutting/data-freshness.md#смена-подключения).
|
||||
|
||||
## Конфигурация и ограничения
|
||||
|
||||
Backend хранит token в шифротексте AES-256-GCM с новым nonce при каждом
|
||||
сохранении. Ключ находится только в серверном окружении. Расшифровка нужна
|
||||
серверной интеграции; ни шифротекст, ни token не входят в публичное API.
|
||||
Причины границы и шифрования сохранены в
|
||||
[ADR 003](../adr/003-tbank-server-side-grpc-boundary.md) и
|
||||
[ADR 004](../adr/004-encrypted-per-user-tbank-token.md).
|
||||
|
||||
| Настройка | Значение и смысл |
|
||||
| --- | --- |
|
||||
| `TOKEN_ENCRYPTION_KEY` | Обязательный ключ AES-256-GCM: 32 байта, закодированные в base64 |
|
||||
| `TBANK_GRPC_ENDPOINT` | Адрес gRPC; по умолчанию `invest-public-api.tbank.ru:443` |
|
||||
| `TBANK_RATE_LIMIT_PER_SECOND` | Число стартующих T-Bank RPC в секунду на экземпляр backend; по умолчанию `5` |
|
||||
| `TBANK_CA_CERT_PATH` | Необязательный путь к доверенному корневому CA в PEM для сетей с TLS-инспекцией; проверка TLS сохраняется |
|
||||
|
||||
Параметры окружения определяет backend
|
||||
[validateEnv](../../backend/src/config/env.validation.ts) (workspace-ссылка).
|
||||
Общий FIFO-лимитер ограничивает поток RPC и отклоняет новый вызов при 50
|
||||
ожидающих. Для `UNAVAILABLE`, `DEADLINE_EXCEEDED` и `RESOURCE_EXHAUSTED`
|
||||
предусмотрен один повтор через секунду. Deadline каждой попытки — 15 секунд,
|
||||
а ожидание места в лимитере не является временем этой сетевой попытки.
|
||||
Параметры попыток принадлежат
|
||||
[T-Bank client](../../backend/src/tbank/tbank.client.ts) (workspace-ссылка);
|
||||
решение об ограниченных повторах — [ADR 005](../adr/005-tbank-upstream-resilience.md).
|
||||
|
||||
Большое число ранее неизвестных инструментов требует отдельных запросов
|
||||
metadata. При перегруженной очереди необязательные имена могут быть заменены
|
||||
идентификаторами; это не доказывает потерю самой позиции. Изменение локального
|
||||
лимита требует учёта разрешённой квоты T-Bank: оно не увеличивает квоту
|
||||
поставщика. Диагностика соединения описана в
|
||||
[локальном окружении](../development/local-workspace.md).
|
||||
|
||||
Ключ шифрования не ротируется автоматически. Лимитер и кэши принадлежат
|
||||
одному экземпляру; изменения подключения не координируются между
|
||||
распределёнными экземплярами backend. Интеграция использует сохранённый
|
||||
protobuf-контракт T-Bank: обновление внешнего протокола и проверка
|
||||
совместимости требуют отдельного изменения интеграции.
|
||||
Reference in New Issue
Block a user