docs: explain persisted T-Bank reads and synchronization
Conventional commits / commits (pull_request) Successful in 14s
Docs security / security (pull_request) Successful in 8s
Docs verify / verify (pull_request) Successful in 13s
Docs security / security (push) Successful in 8s
Docs verify / verify (push) Successful in 12s

Document local data ownership, coverage and freshness, refresh behavior, failure
recovery and additive migration rollback. Record ADR 017.
This commit was merged in pull request #22.
This commit is contained in:
2026-09-26 21:22:50 +03:00
parent 55610ea2b4
commit 07de062ebb
19 changed files with 459 additions and 432 deletions
+25 -37
View File
@@ -46,8 +46,9 @@ ID операций разных счетов не означают дублик
На [страницах акций](../instruments/stocks.md) и
[облигаций](../instruments/bonds.md) этот же журнал становится личной историей
конкретной бумаги. Фильтр `instrumentUid` передаётся брокеру и проверяется
в ответе. Без явного начала периода он охватывает историю с открытия счёта;
конкретной бумаги. Фильтр `instrumentUid` применяется к локальным операциям. Ручная сверка
личной истории может ограничить источниковый запрос этой бумагой, не присваивая
такому subset полноту всех операций счёта. Без явного начала периода он охватывает историю с открытия счёта;
в общем режиме — с самой ранней известной даты открытия доступных счетов.
Если даты открытия неполны, нижняя граница — Unix epoch. Это позволяет
видеть прошлые операции уже проданной бумаги, но не обещает историю
@@ -55,43 +56,29 @@ ID операций разных счетов не означают дублик
## Получение и полнота
```mermaid
sequenceDiagram
participant F as Frontend
participant B as Backend
participant T as T-Bank
F->>B: Запрашивает применённый период и страницу операций
B->>B: Проверяет сессию и текущее подключение
B->>T: Получает открытые счета
T-->>B: Подтверждает доступность счёта
alt Подходящая страница есть в кэше
B-->>F: Сохранённая страница
else Нужна загрузка
B->>T: GetOperationsByCursor, только исполненные операции
T-->>B: Страница операций
B->>B: Нормализует записи и применяет фильтры
B-->>F: Записи и продолжение либо ошибка
end
```
`GET /api/v1/brokerage-accounts/:accountId/operations` читает сохранённые
операции и coverage после локальной проверки доступа. Период, категории,
UID, cursor и limit применяются к этой выборке. Транспорт описан в
[HTTP API](../../architecture/http-api.md).
`GET /api/v1/brokerage-accounts/:accountId/operations` требует Bearer token.
Период, категории, необязательный UID, курсор и размер страницы задают запрос;
ответ содержит записи, время наблюдения и сведения о продолжении.
Точные поля и допустимые значения задаёт [HTTP API](../../architecture/http-api.md).
Стабильность broker operation ID в пределах счёта и подключения принята как
допущение проекта. Повторный ID обновляет ту же запись без двойного учёта.
Страницы источника сначала сохраняются в staging. Полный успешный обход
разрешает upsert, удаление исчезнувших записей в перечитанном predicate
и публикацию coverage одной транзакцией. При повторной сверке полного
показанного периода транзакция охватывает все его окна и счета.
Backend хранит не более 100 страниц в памяти процесса. Свежая страница
живёт до 30 секунд; при переполнении вытесняется давно не использовавшаяся.
Ключ разделяет пользователя, поколение подключения, счёт, нормализованный
период и категории, UID инструмента, курсор и размер страницы.
Отсутствующий конец периода приводится к текущему 30-секундному интервалу.
Текущее подключение и доступ к счёту проверяются до выдачи страницы из кэша.
Полнота относится к UTC-интервалу `[from,to)`, включая подтверждённый пустой.
Категории, размер страницы и `hasNext=false` её не определяют. При первичном
импорте подтверждённые строки видны как partial; итоги ждут полного периода.
Догрузка остальной истории обозначается отдельно. Без известной нижней
границы нельзя заявить полную историю счёта.
После успешного изменения подключения страницы предыдущего поколения,
в том числе поздно завершившиеся запросы, не выдаются журналу или аналитике
дохода. Они удаляются по обычным ограничениям времени и объёма.
Локальной синхронизации и долговременного хранения операций нет.
Продолжения [общего журнала](../portfolio/all-accounts.md#общая-пагинация-операций)
имеют собственные ограничения и восстановление после истечения.
Cursor связан с пользователем, подключением, membership для `all`, фильтрами
и ревизией набора операций. Изменение строк даёт `INVALID_OPERATIONS_CURSOR`;
клиент возвращается на первую страницу, сохраняя применённые фильтры.
Coverage/status без изменения rowset cursor не ломают. Перезапуск сохраняет
опубликованные интервалы; незавершённая работа возобновляется только запросом.
## Представление и ошибки
@@ -110,7 +97,8 @@ Backend хранит не более 100 страниц в памяти проц
не заменяется каркасом при применении действий или фоновом обновлении.
Ошибки `TBANK_NOT_CONNECTED`, `INVALID_TBANK_TOKEN`, недоступный счёт (`404`)
и `TBANK_UNAVAILABLE` сохраняют [общую семантику API](../../architecture/http-api.md).
Пустой успешный ответ означает отсутствие подходящих операций, а не сбой.
Только полный пустой ответ означает отсутствие подходящих операций.
Partial empty сообщает о неполноте; source failure сохраняет прежний результат.
Согласованное поведение описано в [спецификации журнала](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-ledger/spec.md).
Фильтр конкретной бумаги и общий режим расширяют исходное описание отдельного