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

96 lines
15 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.
## 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`.