Files
specs/openspec/changes/archive/2026-10-09-persist-tbank-data/specs/brokerage-account-ledger/spec.md
T
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

15 KiB
Raw Blame History

MODIFIED Requirements

Requirement: User can retrieve an account ledger

Система MUST предоставлять аутентифицированный журнал только для чтения выбранного Brokerage Account либо существующего режима «Все счета» (all) в границах текущего User и его T-Bank connection. В режиме all доступ MUST проверяться для каждого входящего счёта, операции MUST сохранять принадлежность исходному счёту, а полнота периода MUST учитывать покрытие каждого входящего счёта. Журнал MUST содержать только исполненные операции T-Bank и при отсутствии периода по умолчанию охватывать интервал от начала текущего календарного года в UTC до момента запроса.

Система MUST читать сохранённые операции и локальное подтверждение доступа текущего подключения без синхронного обращения к T-Bank, включая запрос списка счетов. Ответ MUST содержать envelope { data, meta } по tbank-data-sync, отражающий полноту запрошенного периода независимо от текущей страницы. Отсутствующие данные MUST возвращаться с data: null и состоянием загрузки, а частично сохранённый период MUST обозначаться как partial. Только подтверждённо полный пустой период MUST обозначать отсутствие операций.

Scenario: Получение журнала с периодом по умолчанию

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

Scenario: Отклонение недоступного счёта

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

Scenario: Общий журнал содержит неполный счёт

  • WHEN User запрашивает режим all и у одного из разрешённых счетов есть незагруженный интервал периода
  • THEN система возвращает только разрешённые сохранённые записи с принадлежностью счёту и обозначает общий период неполным, не подменяя отсутствующий вклад пустым счётом

Scenario: Пустая загруженная часть не доказывает отсутствие операций

  • WHEN в сохранённой части периода нет записей, но покрытие периода не завершено
  • THEN ответ обозначает неполноту и запрошенную загрузку, а интерфейс не сообщает, что операций за период нет

Requirement: User can browse a filtered ledger

Система MUST позволять User ограничивать журнал включительным периодом дат и любым подмножеством категорий trade, income, tax, fee, transfer, other. Система MUST фильтровать сохранённые операции локально, не перечитывая T-Bank из-за категории, instrument UID, размера страницы или перехода между страницами полного периода. Система MUST разбивать упорядоченный результат на страницы с непрозрачным cursor и возвращать признак доступности следующей страницы.

Cursor MUST быть привязан к User, текущему подключению, составу счетов, применённым фильтрам, зафиксированной верхней границе периода и версии читаемых данных. Курсор другой границы или изменившейся версии MUST отклоняться существующим INVALID_OPERATIONS_CURSOR, позволяя повторить первую страницу с прежними фильтрами. Доступность следующей локальной страницы MUST NOT заменять признак полноты периода. Равнозначные порядок и дубли categories MUST NOT создавать другую идентичность запроса.

Scenario: Фильтрация доходных операций за период

  • WHEN User запрашивает период дат и категорию income
  • THEN результат содержит только исполненные доходные операции с датой в пределах этого периода

Scenario: Продолжение истории

  • WHEN User запрашивает cursor следующей страницы, возвращённый предыдущим ответом журнала, и версия данных не изменилась
  • THEN система возвращает следующую страницу без повторения записей предыдущей страницы

Scenario: Обновление изменило данные между страницами

  • WHEN после выдачи первой страницы успешная синхронизация изменила её набор операций и User передаёт прежний cursor
  • THEN система возвращает INVALID_OPERATIONS_CURSOR, а повторная загрузка начинает первую страницу с сохранёнными применёнными фильтрами без пропуска или дублирования записей

Scenario: Полный период фильтруется локально

  • WHEN User меняет категории или страницы в полностью сохранённом прошлом периоде
  • THEN система формирует результат из сохранённых операций без нового запроса операций T-Bank

Requirement: Ledger entries preserve broker operation meaning

Система MUST представлять одну upstream-операцию одной записью журнала и MUST передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, доступную presentation metadata инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля MUST сохранять исходную валюту и точное десятичное значение.

В пределах текущего подключения идентичность Ledger Entry MUST включать User, Brokerage Account и upstream operation ID. Повторное получение того же ID MUST обновлять доступные поля этой операции без создания второй записи; одинаковые ID разных счетов MUST оставаться разными записями. Стабильность ID MUST считаться допущением проекта, а не гарантией T-Bank.

Scenario: Отображение купонной выплаты

  • WHEN T-Bank возвращает исполненную купонную операцию с выплатой и данными инструмента
  • THEN запись журнала определяет её как income и передаёт исходную сумму выплаты, валюту и данные инструмента

Scenario: Отображение комиссии сделки без синтетической записи

  • WHEN T-Bank возвращает исполненную сделку, содержащую выплату и комиссию
  • THEN журнал содержит одну запись сделки с комиссией в качестве её детали

Scenario: Отображение движения бумаг без денег

  • WHEN T-Bank возвращает исполненную операцию, изменяющую состав инструментов, но без денежной выплаты
  • THEN запись журнала передаёт доступное количество и не содержит искусственной денежной выплаты с нулевым значением

Scenario: Доступна визуальная идентичность инструмента

  • WHEN для инструмента исполненной операции доступна presentation metadata бренда
  • THEN запись журнала передаёт её вместе с доступными идентификаторами инструмента, не меняя остальные сведения операции

Scenario: Повторная операция содержит исправленные поля

  • WHEN успешная синхронизация получает операцию с уже сохранённым ID того же счёта и изменёнными полями
  • THEN последующее чтение возвращает одну запись с обновлёнными полями без удвоения денежного движения

Requirement: Account overview includes recent ledger events

Обзор счёта MUST показывать не более пяти последних сохранённых исполненных записей журнала этого счёта с состоянием полноты и загрузки требуемого периода и действие перехода к его полному журналу. Каждая показанная запись MUST иметь ту же визуальную идентичность инструмента и семантику денежного движения, что и запись полного журнала. Неуспешный или пустой запрос последних записей MUST оставаться локальным состоянием блока последних событий и MUST NOT заменять успешно отображённый обзор Portfolio.

Scenario: Отображение последних событий

  • WHEN загружается обзор счёта и его журнал содержит исполненные операции
  • THEN обзор показывает не более пяти последних записей и ссылку на полный журнал

Scenario: Последние записи недоступны

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

Scenario: Последняя запись не содержит visual metadata инструмента

  • WHEN одна из последних записей не имеет доступной presentation metadata инструмента
  • THEN обзор показывает для неё понятный текстовый fallback и сохраняет дату, тип, инструмент и денежное изменение записи доступными для чтения

Scenario: Первичная история обзора неполна

  • WHEN обзор получил только часть требуемых операций или data: null
  • THEN блок обозначает загрузку или неполноту и не утверждает, что показанные записи окончательны либо операции отсутствуют

REMOVED Requirements

Requirement: Кэш страниц журнала ограничивает локальные ресурсы

Reason: Постоянное хранение операций и запросная синхронизация заменяют обязательный RAM-кэш на 100 страниц с TTL 30 секунд; его запрет на выдачу старой страницы противоречит локальному чтению сохранённой истории.

Migration: Чтение, свежесть, объединение загрузок и сохранение прогресса переходят к tbank-data-sync; локальная фильтрация и привязанный к версии данных cursor регулируются User can browse a filtered ledger. Существующие transient cursors не являются доказательством полноты и при несовместимости возвращают INVALID_OPERATIONS_CURSOR.