From 7edfcb9dba35f75ce76f97e643c2e7492afdd82c Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Thu, 13 Aug 2026 19:37:42 +0300 Subject: [PATCH] docs: archive T-Bank connection change --- .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/tbank-connection/spec.md | 0 .../2026-08-12-add-tbank-connection}/tasks.md | 0 openspec/specs/tbank-connection/spec.md | 81 +++++++++++++++++++ 6 files changed, 81 insertions(+) rename openspec/changes/{add-tbank-connection => archive/2026-08-12-add-tbank-connection}/.openspec.yaml (100%) rename openspec/changes/{add-tbank-connection => archive/2026-08-12-add-tbank-connection}/design.md (100%) rename openspec/changes/{add-tbank-connection => archive/2026-08-12-add-tbank-connection}/proposal.md (100%) rename openspec/changes/{add-tbank-connection => archive/2026-08-12-add-tbank-connection}/specs/tbank-connection/spec.md (100%) rename openspec/changes/{add-tbank-connection => archive/2026-08-12-add-tbank-connection}/tasks.md (100%) create mode 100644 openspec/specs/tbank-connection/spec.md diff --git a/openspec/changes/add-tbank-connection/.openspec.yaml b/openspec/changes/archive/2026-08-12-add-tbank-connection/.openspec.yaml similarity index 100% rename from openspec/changes/add-tbank-connection/.openspec.yaml rename to openspec/changes/archive/2026-08-12-add-tbank-connection/.openspec.yaml diff --git a/openspec/changes/add-tbank-connection/design.md b/openspec/changes/archive/2026-08-12-add-tbank-connection/design.md similarity index 100% rename from openspec/changes/add-tbank-connection/design.md rename to openspec/changes/archive/2026-08-12-add-tbank-connection/design.md diff --git a/openspec/changes/add-tbank-connection/proposal.md b/openspec/changes/archive/2026-08-12-add-tbank-connection/proposal.md similarity index 100% rename from openspec/changes/add-tbank-connection/proposal.md rename to openspec/changes/archive/2026-08-12-add-tbank-connection/proposal.md diff --git a/openspec/changes/add-tbank-connection/specs/tbank-connection/spec.md b/openspec/changes/archive/2026-08-12-add-tbank-connection/specs/tbank-connection/spec.md similarity index 100% rename from openspec/changes/add-tbank-connection/specs/tbank-connection/spec.md rename to openspec/changes/archive/2026-08-12-add-tbank-connection/specs/tbank-connection/spec.md diff --git a/openspec/changes/add-tbank-connection/tasks.md b/openspec/changes/archive/2026-08-12-add-tbank-connection/tasks.md similarity index 100% rename from openspec/changes/add-tbank-connection/tasks.md rename to openspec/changes/archive/2026-08-12-add-tbank-connection/tasks.md diff --git a/openspec/specs/tbank-connection/spec.md b/openspec/specs/tbank-connection/spec.md new file mode 100644 index 0000000..eaba473 --- /dev/null +++ b/openspec/specs/tbank-connection/spec.md @@ -0,0 +1,81 @@ +# tbank-connection Specification + +## Purpose + +Позволяет авторизованному пользователю безопасно подключить T-Bank Invest для будущего получения только собственных инвестиционных данных через backend. + +## 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: }` без 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: }` + +#### 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