Files
specs/openspec/changes/archive/2026-08-12-add-tbank-connection/specs/tbank-connection/spec.md
T

80 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Purpose
Позволяет авторизованному пользователю безопасно подключить T-Bank Invest для будущего получения только собственных инвестиционных данных через backend.
## ADDED Requirements
### Requirement: Статус подключения T-Bank
Система SHALL предоставлять авторизованному User `GET /api/v1/tbank-connection`, возвращающий состояние его единственного подключения в форме `{ connected, connectedAt }`. При отсутствии подключения ответ MUST быть `{ connected: false, connectedAt: null }`; при наличии подключения `connectedAt` MUST быть timestamp в RFC 3339 UTC. Получение статуса MUST NOT обращаться к T-Bank.
#### Scenario: Подключение отсутствует
- **WHEN** авторизованный User запрашивает статус без сохранённого подключения
- **THEN** система отвечает `200` с `{ connected: false, connectedAt: null }`
#### Scenario: Подключение существует
- **WHEN** авторизованный User запрашивает статус после успешного подключения
- **THEN** система отвечает `200` с `{ connected: true, connectedAt: <RFC 3339 UTC timestamp> }` без token
### Requirement: Создание и замена подключения T-Bank
Система SHALL позволять авторизованному User создать или заменить единственное подключение через `PUT /api/v1/tbank-connection` с token. Система MUST удалить внешние пробелы token, отклонить пустое значение как ошибку валидации и проверить token запросом T-Bank открытых счетов до сохранения. Пустой список счетов MUST считаться успешной проверкой. Успех MUST вернуть `200` с текущим статусом подключения; успешная замена MUST установить новый `connectedAt`.
#### Scenario: Успешное создание подключения без счетов
- **WHEN** User отправляет непустой token и T-Bank успешно возвращает пустой список открытых счетов
- **THEN** система сохраняет подключение и отвечает `200` с `{ connected: true, connectedAt: <RFC 3339 UTC timestamp> }`
#### Scenario: Успешная замена подключения
- **WHEN** User с подключением отправляет другой token и T-Bank успешно его проверяет
- **THEN** система заменяет token подключения, обновляет `connectedAt` и отвечает текущим статусом без token
#### Scenario: Невалидный token не заменяет существующее подключение
- **WHEN** T-Bank отклоняет token как неаутентифицированный или не имеющий прав
- **THEN** система отвечает `400` Problem Details с code `INVALID_TBANK_TOKEN` и сохраняет прежнее подключение без изменений
#### Scenario: T-Bank временно недоступен при проверке token
- **WHEN** проверка token не завершается из-за временной или иной upstream-ошибки
- **THEN** система отвечает `503` Problem Details с code `TBANK_UNAVAILABLE` и не создаёт либо не изменяет подключение
### Requirement: Удаление подключения T-Bank
Система SHALL позволять авторизованному User удалить своё подключение через `DELETE /api/v1/tbank-connection`. Удаление MUST быть идемпотентным и отвечать `204`; после успешного удаления backend MUST прекратить использовать удалённый token и удалить относящиеся к User кэшированные данные T-Bank.
#### Scenario: Удаление существующего подключения
- **WHEN** User удаляет существующее подключение
- **THEN** система удаляет token и связанные кэшированные данные User, затем отвечает `204`
#### Scenario: Повторное удаление подключения
- **WHEN** User удаляет уже отсутствующее подключение
- **THEN** система отвечает `204`
### Requirement: Конфиденциальность token T-Bank
Система MUST хранить не более одного token T-Bank для каждого User только в зашифрованном виде. Token MUST расшифровываться только для серверного вызова T-Bank и MUST NOT передаваться в frontend, HTTP-ответах, OpenAPI examples, сообщениях ошибок или application logs.
#### Scenario: API не раскрывает token
- **WHEN** User создаёт, заменяет, удаляет или получает статус подключения
- **THEN** ни один HTTP-ответ не содержит token или его фрагмент
### Requirement: Устойчивость проверки T-Bank
Система SHALL выполнять проверку token только через защищённое TLS-подключение к T-Bank. Все вызовы T-Bank MUST проходить через общий для экземпляра backend лимит, задаваемый конфигурацией и равный 5 запросам в секунду по умолчанию, с FIFO-очередью не более 50 ожидающих вызовов. Для временных ошибок система MUST выполнить не более одного повторного вызова; если проверка не завершается успешно, token MUST NOT сохраняться.
#### Scenario: Лимит ожидания upstream-вызовов исчерпан
- **WHEN** 50 вызовов T-Bank уже ожидают общий лимитер
- **THEN** следующий запрос не обращается к T-Bank и получает `503` Problem Details с code `TBANK_UNAVAILABLE`
#### Scenario: Временная ошибка успешно повторяется
- **WHEN** первая проверка token завершается временной ошибкой, а единственный повтор завершается успешно
- **THEN** система сохраняет подключение и отвечает текущим статусом
### Requirement: Управление подключением в настройках
Клиент SHALL показывать в настройках статус T-Bank connection, текст о необходимости read-only T-Bank Invest token, поле token и действие подключения либо замены. Для существующего подключения клиент MUST показывать действие удаления с modal-подтверждением. Во время создания, замены или удаления все действия секции подключения и действия modal MUST быть отключены. После успешного создания или замены клиент MUST очистить поле token и обновить статус; при ошибке token MUST остаться в поле.
#### Scenario: Пользователь подтверждает удаление
- **WHEN** User подтверждает удаление в modal
- **THEN** клиент блокирует действия секции до результата и после успешного ответа показывает состояние без подключения
#### Scenario: Ошибка загрузки статуса
- **WHEN** клиент не может получить статус подключения
- **THEN** клиент показывает отдельное error-состояние с возможностью повторить запрос и не показывает форму подключения
#### Scenario: Ошибка проверки token в клиенте
- **WHEN** создание или замена получает `INVALID_TBANK_TOKEN` либо `TBANK_UNAVAILABLE`
- **THEN** клиент показывает соответственно локализованное сообщение о token и правах либо о временной недоступности T-Bank, возвращает интерактивность и сохраняет введённый token