Files
ksv741 329d66e767
Specs security / security (push) Successful in 8s
Specs verify / verify (push) Successful in 11s
spec: finalize wealth-ledger SDD migration
2026-10-09 21:14:22 +03:00

13 KiB
Raw Blame History

MODIFIED Requirements

Requirement: Получение Portfolio выбранного Brokerage Account

Система SHALL предоставлять авторизованному User GET /api/v1/brokerage-accounts/:accountId/portfolio. Она MUST возвращать нормализованный полный Portfolio Snapshot только для открытого поддерживаемого Brokerage Account, доступного через текущий T-Bank connection User. Ответ MUST иметь envelope { data, meta }: data MUST содержать сохранённый полный Portfolio Snapshot с lastSuccessfulAt в RFC 3339 UTC без миллисекунд, boolean isStale, totalsByCurrency, positions и cashBalances; meta MUST содержать наблюдаемое состояние resource по tbank-data-sync, включая freshness, полноту, время последнего успешного Snapshot, последнюю часовую попытку и доступность. Обычный GET MUST читать сохранённый Snapshot и его наблюдаемое состояние без ожидания T-Bank и MUST NOT запускать обновление личного Portfolio.

Portfolio Snapshot является результатом наблюдения Portfolio на конкретный момент. Он MUST NOT означать, что WealthLedger хранит Portfolio как долговременный агрегат или подтверждает доступность Brokerage Account вне текущего T-Bank connection.

Scenario: Получение текущего Portfolio

  • WHEN User запрашивает Portfolio доступного Brokerage Account, а полный Snapshot текущего подключения успешно сохранён
  • THEN система отвечает 200 с полным нормализованным Portfolio Snapshot в data, его lastSuccessfulAt и isStale, а также наблюдаемым состоянием в meta

Scenario: Недоступный Brokerage Account

  • WHEN accountId не принадлежит User, закрыт, неподдерживаем или больше не доступен через текущий T-Bank connection
  • THEN система отвечает 404 без Portfolio Snapshot

Requirement: Свежесть и fallback полного Portfolio Snapshot

Система MUST хранить последний полный успешно полученный Portfolio Snapshot с принадлежностью User, экземпляру подключения и Brokerage Account. Обычный GET MUST возвращать { data, meta }, где data является сохранённым Snapshot, а meta соответствует наблюдаемому состоянию resource по tbank-data-sync, читать его без ожидания T-Bank и MUST NOT запускать обновление личного Portfolio, даже если Snapshot отсутствует или старше 60 минут; обновлением владеет часовой обход. Portfolio source MUST считаться свежим в течение 60 минут после успешного получения. Ошибка обхода MUST сохранять прежний полный Snapshot и его время без лимита fallback. Если состав получен полностью, но отдельная позиция не имеет цены, система MUST сохранить новый состав с неполной оценкой; metadata MUST NOT определять успешность или свежесть финансового Snapshot. Сохранённая доступная identity позиции MAY оставаться доступной при недоступности online-справочника.

Система MUST делать прежние личные datasets недоступными после успешной замены или удаления подключения. Поздняя работа прежнего подключения MUST NOT публиковаться в новом. Самостоятельные справочные сведения и результаты lookup MUST запрашиваться онлайн, а не сохраняться как долговременный справочник; ошибка lookup не подтверждает отсутствие инструмента.

Scenario: Свежий Snapshot

  • WHEN User повторно запрашивает тот же Portfolio в течение 60 минут после успешного получения
  • THEN система возвращает свежий Snapshot без нового обращения к T-Bank

Scenario: Медленный lookup инструмента

  • WHEN сведения об инструменте ещё запрашиваются онлайн
  • THEN система не задерживает локальный ответ Portfolio ради lookup и показывает сохранённую доступную identity

Scenario: Fallback после временной upstream-ошибки

  • WHEN часовой обход Portfolio неуспешен из-за временной недоступности T-Bank, а в текущей границе подключения есть полный успешный Snapshot
  • THEN система отвечает 200 этим Snapshot с isStale: true и исходным lastSuccessfulAt

Scenario: Недействительный token не маскируется fallback-данными

  • WHEN T-Bank отклоняет token как неаутентифицированный или без прав при часовом обходе Portfolio
  • THEN система не возвращает fallback Snapshot и отвечает 400 Problem Details с code INVALID_TBANK_TOKEN

Scenario: Неполная оценка при новом составе

  • WHEN успешно получен полный состав позиций, но у одной позиции нет вычислимой цены
  • THEN новый состав становится текущим Portfolio Snapshot с неизвестной стоимостью позиции без подстановки нуля

Requirement: Состояния и ошибки Portfolio на клиенте

Клиент SHALL загружать Portfolio при открытии защищённого маршрута /accounts/:accountId. Он MUST использовать успешный ответ в течение 30 секунд без automatic retry или refetch при возврате фокуса. Открытый экран MUST перечитывать сохранённый результат backend каждые 30 минут без запуска синхронизации T-Bank. Клиент MUST показывать freshness, полноту, время последнего успешного Snapshot, последнюю часовую попытку и доступность из meta текстом или доступно именованным элементом, а не только цветом. Клиент MUST NOT предоставлять действие ручной синхронизации Portfolio. При отсутствии ранее успешного ответа он MUST показывать структурный skeleton с доступным обозначением занятости без вымышленных сумм; skeleton MUST NOT быть интерактивным или получать клавиатурный фокус.

Истечение срока свежести MUST NOT скрывать Client Cached Snapshot. Во время фонового перечитывания и после его ошибки клиент MUST сохранять ранее полученные данные того же Portfolio, исходное lastSuccessfulAt и показывать неблокирующую индикацию либо предупреждение с действием повтора только HTTP-чтения. Сохранённые данные MUST NOT считаться новым успешным снимком или подтверждением текущей доступности Brokerage Account. При isStale: true клиент MUST показывать Snapshot, исходное время и нейтральное предупреждение без действия ручного обновления. Server-side stale и ошибка Client Cached Snapshot MUST оставаться раздельными состояниями.

При отсутствии Client Cached Snapshot и ответе 404 клиент MUST показать недоступный счёт с возвратом к списку без действия повтора. При отсутствии Snapshot и TBANK_NOT_CONNECTED, INVALID_TBANK_TOKEN, TBANK_UNAVAILABLE либо иной ошибке клиент MUST показать безопасное error-состояние; повтор HTTP-чтения разрешён только для временной и неизвестной ошибки.

Scenario: Показ устаревшего Portfolio

  • WHEN клиент получает успешный ответ с isStale: true
  • THEN клиент показывает Portfolio, исходное время и нейтральное предупреждение без ручной синхронизации

Scenario: Первичная загрузка Portfolio

  • WHEN клиент ожидает Portfolio без ранее полученного успешного ответа
  • THEN он показывает структурный skeleton без вымышленных или нулевых сумм и без фокусируемых placeholders

Scenario: Неуспешная последняя попытка сохраняет Portfolio

  • WHEN клиент получает полный Portfolio и meta с неуспехом последней часовой попытки
  • THEN он сохраняет Portfolio и исходное время видимыми и отдельно показывает текстовое либо доступно именованное предупреждение о неуспехе попытки

Scenario: Недоступный счёт на клиенте

  • WHEN для текущего Portfolio отсутствует Client Cached Snapshot и клиент получает 404
  • THEN клиент не показывает Portfolio и предлагает вернуться к списку Brokerage Account без действия повтора

Scenario: Обновление после истечения срока свежести

  • WHEN срок свежести показанного Portfolio истёк и началось фоновое HTTP-перечитывание
  • THEN клиент сохраняет прежние валютные итоги и время, показывает неблокирующую индикацию и не заменяет данные skeleton-состоянием

Scenario: Ошибка обновления после успешного ответа

  • WHEN Client Cached Snapshot Portfolio уже видим, а повторное HTTP-чтение завершается ошибкой
  • THEN клиент сохраняет прежние данные и время, показывает неблокирующее предупреждение и действие повтора чтения

Scenario: Ошибка клиентского обновления при server-side stale

  • WHEN клиент показывает Portfolio с isStale: true, а фоновое перечитывание завершается ошибкой
  • THEN оба предупреждения остаются различимыми, а действие повтора относится только к HTTP-чтению

Scenario: Повторное обновление успешно

  • WHEN после ошибки HTTP-чтения User запускает повторное чтение и получает успешный Portfolio Snapshot
  • THEN клиент показывает значения и lastSuccessfulAt успешного ответа, убирает предупреждение об ошибке чтения и отображает server-side предупреждение только по новому isStale

Scenario: Штатный пустой Portfolio на клиенте

  • WHEN успешно полученный Portfolio содержит пустые positions и cashBalances
  • THEN клиент показывает empty-состояние без валютных карточек с вымышленными нулевыми итогами