chore(release): 0.1.4 #38

Merged
codex-bot merged 16 commits from release/0.1.4 into main 2026-10-13 07:43:17 +03:00
28 changed files with 450 additions and 148 deletions
+15
View File
@@ -0,0 +1,15 @@
---
name: Bug Report
about: Неверное поведение
---
# Bug Report
## Проблема и шаги воспроизведения
## Факт / ожидание
## Acceptance Criteria
- [ ]
## Окружение / ссылки (если применимо)
+13
View File
@@ -0,0 +1,13 @@
---
name: Engineering Task
about: CI, тесты, документация, процесс и прочее
---
# Engineering Task
## Контекст и результат
## Scope / связанные Issues (если есть)
## Acceptance Criteria
- [ ]
+15
View File
@@ -0,0 +1,15 @@
---
name: Feature Request
about: Новое наблюдаемое поведение
---
# Feature Request
## Зачем и какой результат
## Ожидаемое поведение
## Acceptance Criteria
- [ ]
## Зависимости / связанные Issues (если есть)
+15
View File
@@ -0,0 +1,15 @@
---
name: Refactoring / Technical Debt
about: Улучшение без нового поведения
---
# Refactoring / Technical Debt
## Проблема и результат
## Сохраняемые инварианты / границы
## Acceptance Criteria
- [ ]
## Зависимости / ссылки (если есть)
+19
View File
@@ -0,0 +1,19 @@
# Pull Request
## Summary
Краткий результат работы описывается здесь.
## Linked Issue
Refs `<owner/repo#number>` (заменить ссылкой на реальную Issue).
## Changes
Затронутые части и изменения.
## Verification
- Команда / результат / ограничения:
## Breaking Changes (если есть)
+9 -1
View File
@@ -2,7 +2,11 @@ name: Conventional commits
on: on:
pull_request: pull_request:
types: [opened, synchronize, reopened, edited] types: [opened, synchronize, reopened]
concurrency:
group: docs-commits-${{ gitea.event.pull_request.number }}
cancel-in-progress: true
jobs: jobs:
commits: commits:
@@ -23,4 +27,8 @@ jobs:
HEAD_SHA: ${{ github.event.pull_request.head.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: | run: |
printf '%s\n' "$PR_TITLE" | npm run commitlint -- --strict printf '%s\n' "$PR_TITLE" | npm run commitlint -- --strict
if [[ "$PR_TITLE" =~ ^chore\(release\):\ [0-9]+\.[0-9]+\.[0-9]+$ ]]; then
npm run commitlint -- --strict --from "$HEAD_SHA^" --to "$HEAD_SHA"
else
npm run commitlint -- --strict --from "$BASE_SHA" --to "$HEAD_SHA" npm run commitlint -- --strict --from "$BASE_SHA" --to "$HEAD_SHA"
fi
+6 -2
View File
@@ -2,12 +2,16 @@ name: Docs security
on: on:
push: push:
branches: branches: [develop, main]
- '**'
pull_request: pull_request:
types: [opened, synchronize, reopened]
schedule: schedule:
- cron: '17 5 * * *' - cron: '17 5 * * *'
concurrency:
group: docs-security-${{ gitea.event_name }}-${{ gitea.event.pull_request.number || gitea.ref }}
cancel-in-progress: true
jobs: jobs:
security: security:
runs-on: ubuntu-latest runs-on: ubuntu-latest
+6 -1
View File
@@ -2,8 +2,13 @@ name: Docs verify
on: on:
push: push:
branches: ['**'] branches: [develop, main]
pull_request: pull_request:
types: [opened, synchronize, reopened]
concurrency:
group: docs-verify-${{ gitea.event_name }}-${{ gitea.event.pull_request.number || gitea.ref }}
cancel-in-progress: true
jobs: jobs:
verify: verify:
+6 -2
View File
@@ -3,6 +3,9 @@
Перед изменением прочитай [README](README.md) и [CONTRIBUTING](CONTRIBUTING.md), Перед изменением прочитай [README](README.md) и [CONTRIBUTING](CONTRIBUTING.md),
затем только затронутую тему. Docs объясняет систему; требования принадлежат затем только затронутую тему. Docs объясняет систему; требования принадлежат
основным спецификациям, реализация и coding conventions — соседним репозиториям. основным спецификациям, реализация и coding conventions — соседним репозиториям.
До edits найди/создай подходящую Gitea Issue, проверь AC и ветку; чтение
допускается без Issue. Общий маршрут — [Engineering Workflow](https://git.personal.ksv741.ru/WealthLedger/main/src/commit/03b3b59e6ff2ba391f9dfc42a039a96d0d84c1c9/.ai/conventions/engineering-workflow.md)
(main#28; после merge — актуальная версия `develop`).
Проверь существенные факты по локальным тематическим страницам и ADR; Проверь существенные факты по локальным тематическим страницам и ADR;
внешние источники используй как справочные свидетельства, когда они доступны. внешние источники используй как справочные свидетельства, когда они доступны.
@@ -20,7 +23,8 @@
## Ветки и релизы ## Ветки и релизы
Работа — в отдельной ветке от `develop`, затем PR в `develop`; в `main` напрямую Работа — в issue-linked ветке от `develop`, затем PR в `develop`; в `main` напрямую
не пушить. Release/hotfix и синхронизация веток — по [README](README.md#релизы). не пушить. Release/hotfix и синхронизация веток — по [README](README.md#релизы).
Commits и заголовки PR — Conventional Commits; для спецификаций допустим `spec:`. Commits и заголовки PR — Conventional Commits со ссылкой на Issue (кроме release);
для спецификаций допустим `spec:`.
Перед подготовкой релиза прочитай местный README; версии вручную не повышать. Перед подготовкой релиза прочитай местный README; версии вручную не повышать.
+24
View File
@@ -1,5 +1,29 @@
# Changelog # Changelog
## [0.1.4](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.3...v0.1.4) (2026-10-12)
### Bug Fixes
* align docs commitlint workflow (WealthLedger/main[#27](https://git.personal.ksv741.ru/WealthLedger/docs/issues/27)) ([602eb43](https://git.personal.ksv741.ru/WealthLedger/docs/commit/602eb43294509274cbd9003be31f726b6e275a1e))
### Documentation
* clarify card summary totals ([df6f010](https://git.personal.ksv741.ru/WealthLedger/docs/commit/df6f0109ed696a529cf2622e23fceeab8133f932))
* document hourly attempt lifecycle semantics (WealthLedger/backend[#56](https://git.personal.ksv741.ru/WealthLedger/docs/issues/56)) ([1378ac9](https://git.personal.ksv741.ru/WealthLedger/docs/commit/1378ac9fe2fcfd43bd71421e62b02f00069be928))
* document hourly investment reads ([f0cab44](https://git.personal.ksv741.ru/WealthLedger/docs/commit/f0cab445d7e7076bf92a61f1023b8bf51e094d33))
* document hourly sync history ([e0bceea](https://git.personal.ksv741.ru/WealthLedger/docs/commit/e0bceea936239c08f4717e264be23d7f60552398))
* document stock screener ([2c34023](https://git.personal.ksv741.ru/WealthLedger/docs/commit/2c34023af8593f305f7c81e672b4e179c0992cf3))
* pin docs workflow reference (WealthLedger/main[#27](https://git.personal.ksv741.ru/WealthLedger/docs/issues/27)) ([c24e4b9](https://git.personal.ksv741.ru/WealthLedger/docs/commit/c24e4b990aaeffd02e05f7de21942579e452cecf))
### CI
* avoid duplicate PR checks ([4caa5e9](https://git.personal.ksv741.ru/WealthLedger/docs/commit/4caa5e92b7d2597e5c7725b2036007b71ece2abd))
* skip checks on PR metadata edits ([e6fd4f6](https://git.personal.ksv741.ru/WealthLedger/docs/commit/e6fd4f64b81dd73b33959b845a1babcfac1891c8))
### Maintenance
* align docs engineering workflow (WealthLedger/main[#27](https://git.personal.ksv741.ru/WealthLedger/docs/issues/27)) ([eaf7ede](https://git.personal.ksv741.ru/WealthLedger/docs/commit/eaf7ede8414f0df972f9ae7ab9e223a6350b5462))
## [0.1.3](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.2...v0.1.3) (2026-10-07) ## [0.1.3](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.2...v0.1.3) (2026-10-07)
### Bug Fixes ### Bug Fixes
+5 -3
View File
@@ -35,7 +35,7 @@ WealthLedger помогает частному инвестору понимат
| [Операции](domains/operations/overview.md) | Исполненные операции, фильтры и пагинация | | [Операции](domains/operations/overview.md) | Исполненные операции, фильтры и пагинация |
| [Доход](domains/income/overview.md) | Полученные купоны и дивиденды, периоды и состав расчёта | | [Доход](domains/income/overview.md) | Полученные купоны и дивиденды, периоды и состав расчёта |
| [Будущие выплаты](domains/income/upcoming-events.md) | Календарь по текущим позициям и ограничения прогноза | | [Будущие выплаты](domains/income/upcoming-events.md) | Календарь по текущим позициям и ограничения прогноза |
| [Акции](domains/instruments/stocks.md) и [облигации](domains/instruments/bonds.md) | Поиск выпуска, рыночные показатели и личная история | | [Скринер акций](domains/instruments/stocks.md) и [облигации](domains/instruments/bonds.md) | Подбор акций по параметрам, поиск выпуска, рыночные показатели и личная история |
## Найти материал по задаче ## Найти материал по задаче
@@ -72,9 +72,11 @@ WealthLedger помогает частному инвестору понимат
## Релизы ## Релизы
Репозиторий выпускается независимо. `develop` — интеграция, `main` — принятые Репозиторий выпускается независимо. `develop` — интеграция, `main` — принятые
релизы. Работа: `codex/<task>` от актуального `develop`, PR в `develop`. релизы. Обычная работа: issue-linked ветка от актуального `develop`, PR в `develop`;
общие правила — в Engineering Workflow по ссылке из AGENTS.
Обычные PR допускают squash; release и обратная синхронизация сохраняют историю. Обычные PR допускают squash; release и обратная синхронизация сохраняют историю.
Commits и PR titles — Conventional Commits, включая `spec:`. Версии вручную не повышай. Commits и PR titles — Conventional Commits со ссылкой на Issue (кроме release),
включая `spec:`. Версии вручную не повышай.
1. Получи `main`, `develop` и теги: `git fetch origin --tags`. Убедись, что 1. Получи `main`, `develop` и теги: `git fetch origin --tags`. Убедись, что
`develop` содержит последний релиз. Создай `release/<name>` от проверенного `develop` содержит последний релиз. Создай `release/<name>` от проверенного
@@ -1,6 +1,8 @@
# 017. Локальное чтение данных T-Bank и фоновая синхронизация # 017. Локальное чтение данных T-Bank и фоновая синхронизация
**Status:** Accepted — архитектурное направление согласовано. **Status:** Accepted — историческое архитектурное направление. Решения ниже о
request-driven запуске, ручном обновлении и отсутствии периодического обхода
заменены [ADR 019](019-hourly-reads-and-online-instrument-reference.md).
Prefetch policy ниже заменена [ADR 018](018-minimal-runtime-coordination.md): Prefetch policy ниже заменена [ADR 018](018-minimal-runtime-coordination.md):
свечи загружаются по запрошенному диапазону, без предварительной загрузки свечи загружаются по запрошенному диапазону, без предварительной загрузки
@@ -0,0 +1,37 @@
# 019. Часовой обход и онлайн-справочник инструментов
**Status:** Accepted. Заменяет request-driven, manual-refresh и
no-periodic-walk части [ADR 017](017-local-tbank-reads-and-background-sync.md)
и дополняет [ADR 018](018-minimal-runtime-coordination.md).
## Decision
- Личные T-Bank данные текущего подключения обновляются владельцами источников
через durable hourly walk; его результат ограничен этой connection boundary.
Обычный GET и retry читают только сохранённый результат и не запускают
personal work.
- Только первое открытие неподтверждённого исторического интервала operations
и первого неоткрытого диапазона candles может получить соответственно этот
интервал или диапазон. Это не manual sync; повторное чтение не расширяет и не
запускает такую работу заново.
- Portfolio, operations, forecasts и события сохраняют собственные complete
результаты и время последнего успешного чтения. Результат ресурса
(freshness, completeness, `lastSuccessfulAt`, availability) независим от
resource-relevant последней часовой попытки: поздняя partial/failed попытка
не заменяет сохранённый complete result. При его отсутствии `data: null`.
- Detail, company, catalog search и ticker lookup получают ответ онлайн через
существующие integration clients. Их ошибки не заменяют сохранённые
финансовые данные или подписи snapshot.
- Старые справочные строки не являются источником актуальности и удаляются
только отдельной совместимой миграцией после проверки FK и свечей.
- Клиент повторяет открытые инвестиционные GET не чаще одного раза в 30 минут;
retry повторяет чтение и не создаёт screen sync work. Наблюдение последней
попытки, включая Accounts `sync`, не является командой.
## Consequences
Карточки инструментов зависят от доступности публичного upstream в момент
чтения. Финансовые экраны сохраняют последний успешный snapshot, а статус
последнего hourly walk показывается отдельно. OpenAPI backend остаётся
единственным исполняемым источником HTTP-контракта; frontend использует
опубликованный snapshot.
@@ -0,0 +1,42 @@
# 020. Evidence for hourly sync read boundaries
**Status:** Accepted. Evidence for [ADR 019](019-hourly-reads-and-online-instrument-reference.md).
## Measurements
The backend persisted-read budget was measured with `npm run test:performance`
using a synthetic SQLite dataset: three accounts, 100,000 operations per
account, 200 instruments, and 5,000 candles per instrument. The run used Node
24.21.0 on Apple M1 Pro with 32 GiB RAM and a failing synthetic upstream after
population. It measured 100 reads per route family, excluding transport
limiter cost.
The generated evidence is written by the test to its temporary
`persistent-budget.json` file. This is a repeatable measurement, not a
production SLA: it does not include network latency, real T-Bank quotas, or
multi-process SQLite contention.
The successful run produced a 617,263,104-byte SQLite database and measured
zero upstream calls during the persisted-read phase. Backend p50/p95 response
times were approximately 1.3/2.3 ms for account and portfolio reads,
3.9/4.5 ms for account operations, 6.7/7.2 ms for aggregate operations,
40.0/41.5 ms for account income analytics, and 128.1/134.2 ms for aggregate
income analytics. These figures are local synthetic measurements only.
## Durability
The migration durability check passes against a separately built repository at
the pre-history migration prefix. It verifies preservation of users, sessions,
T-Bank connection data, bank-card data, operations, categories, archive state,
and replay behavior across migration and restart.
The executed command was `node test/bank-cards-durability.cjs` with a separately
built pre-history repository. It completed with `PASS durability`.
## Limits
The configured T-Bank start limiter is `TBANK_RATE_LIMIT_PER_SECOND`, default
`5` per backend instance. The hourly scheduler therefore remains a single
durable reservation owner; the measurement does not justify increasing this
limit or changing the hourly cadence. Any production tuning requires current
T-Bank documentation and a new measurement with the deployed topology.
+2
View File
@@ -23,3 +23,5 @@
- [016 — Версионируемый комплект развёртывания](016-versioned-deployment-bundle.md) - [016 — Версионируемый комплект развёртывания](016-versioned-deployment-bundle.md)
- [017 — Локальное чтение данных T-Bank и фоновая синхронизация](017-local-tbank-reads-and-background-sync.md) - [017 — Локальное чтение данных T-Bank и фоновая синхронизация](017-local-tbank-reads-and-background-sync.md)
- [018 — Минимальная runtime-координация](018-minimal-runtime-coordination.md) - [018 — Минимальная runtime-координация](018-minimal-runtime-coordination.md)
- [019 — Часовой обход и онлайн-справочник инструментов](019-hourly-reads-and-online-instrument-reference.md)
- [020 — Evidence for hourly sync read boundaries](020-hourly-sync-verification-evidence.md)
+56 -35
View File
@@ -1,51 +1,72 @@
# Свежесть данных и повторное использование # Свежесть данных и повторное использование
WealthLedger читает инвестиционные данные из SQLite. Обычный GET возвращает WealthLedger читает личные инвестиционные данные из SQLite. Обычный GET и его
сохранённый результат и запрашивает фоновые зависимости, если они отсутствуют HTTP retry возвращают сохранённый результат и не запускают личную работу с
или устарели. HTTP-ответ не ждёт T-Bank. Модель принята в T-Bank. Нормальным владельцем обновления служит часовой обход текущего
[ADR 017](../../adr/017-local-tbank-reads-and-background-sync.md). подключения: после успешного подключения он начинает первую попытку, затем
начинает следующую не ранее чем через 60 минут от начала предыдущей. После
простоя выполняется не более одна актуальная попытка, а перекрывающийся срок
пропускается, не ставится в очередь. Общие справочные данные инструментов
запрашиваются онлайн, когда это требуется карточке; финансовый HTTP-ответ не
ждёт T-Bank. Модель принята в
[ADR 019](../../adr/019-hourly-reads-and-online-instrument-reference.md).
## Клиентский и серверный снимки ## Клиентский и серверный снимки
[Client Cached Snapshot](../../glossary.md#client-cached-snapshot) — успешный [Client Cached Snapshot](../../glossary.md#client-cached-snapshot) — успешный
ответ в TanStack Query. Он сохраняет показанное содержимое при временной ошибке ответ в TanStack Query. Он сохраняет показанное содержимое при временной ошибке
запроса в той же границе доступа. SQLite сохраняет источники независимо от HTTP-перечитывания в той же границе доступа. Это не серверный fallback и не
браузера: membership, последний полный portfolio, исполненные операции, состояние часового обхода. SQLite независимо от браузера хранит membership,
общие сведения об инструментах, котировки, свечи и календари. последний полный portfolio, исполненные операции, прогнозы, общие сведения об
инструментах, котировки, свечи и календари.
[Полнота периода](../../glossary.md#полнота-истории-счёта) и свежесть различаются. [Полнота периода](../../glossary.md#полнота-истории-счёта) и свежесть различаются.
Успешно проверенный пустой интервал полон; последняя страница журнала сама Успешно проверенный пустой результат полон и доступен; последняя страница
по себе полноту не доказывает. Ошибка сверки сохраняет прежние данные и время. журнала сама по себе полноту не доказывает. Результат каждого личного ресурса
Старый полный портфель не удаляется по истечении TTL. `isStale` показывает в `{ data, meta }` описывают пять независимых значений: freshness,
возраст portfolio source, а не сам факт неудачного обновления. completeness, `lastSuccessfulAt`, `lastAttempt` и availability. Первые,
полнота и `lastSuccessfulAt` относятся только к возвращённому подтверждённому
результату. `lastAttempt` описывает относящуюся к ресурсу часовую попытку:
`none`, `running`, `succeeded`, `partial` или `failed`.
| Источник | Когда обычный запрос требует обновления | Итог попытки выводится из фактических результатов её шагов: попытка, не
завершившая обязательный шаг, не обозначается полным успехом, а полученные
успешные результаты сохраняются. Ожидание каждого шага ограничено; зависший
шаг учитывается проблемным, а начатое обращение к T-Bank не отменяется.
Попытка, потерявшая выполнение после сбоя сохранения или остановки процесса,
закрывается частичным успехом либо неуспехом и не блокирует следующий обход
дольше обычного часового срока.
Поздняя неуспешная или частичная попытка сохраняет прежний полный результат и
его исходное время. Если полного результата нет, `data` равно `null`: состояние
availability объясняет первоначальную загрузку, временную недоступность либо
недоступность подключения. Пустой массив не означает отсутствие результата.
Старый полный portfolio не удаляется из-за возраста. `Portfolio.isStale`
сохраняет смысл возраста его snapshot, а не обозначает неуспех обхода или
клиентскую ошибку перечитывания.
| Источник | Владелец нормального обновления |
| --- | --- | | --- | --- |
| Portfolio, котировки, изменяемый хвост дневных свечей | Через 60 секунд | | Membership, portfolio, изменяемый хвост операций и события | Часовой обход текущего подключения |
| Membership и изменяемый хвост операций | Через 5 минут | | Котировки и изменяемый хвост дневных свечей | Установленная политика источника; не ordinary personal GET |
| Metadata, поиск каталога, company и календари | Через сутки | | Metadata, поиск каталога и company | Онлайн при чтении |
| Полные прошлые интервалы операций и завершённые свечи | При явном обновлении показанного периода | | Полные прошлые интервалы операций и завершённые свечи | Не обновляются часовым обходом или обычным GET |
TTL не создаёт таймер импорта. Запрошенная работа может закончиться после Два исключения разрешают только первое получение отсутствующего результата:
ухода со страницы. После перезапуска нет автоматического обхода intent: первое открытие неподтверждённого исторического интервала операций получает
следующий подходящий запрос повторяет незавершённый интервал с первой страницы, только этот интервал и возвращает локальные строки с неполным покрытием; первое
переиспользуя полные интервалы. Cursor брокера не служит durable checkpoint. открытие диапазона свечей без подтверждённого локального результата получает
только этот диапазон. Ни одно исключение не обновляет membership, portfolio,
события, другой интервал или диапазон. Их HTTP retry также только перечитывает
локальное состояние. Подтверждённый полный интервал или диапазон остаётся
локальным.
Ручное «Обновить» перечитывает зависимости текущего экрана и применённый Часовой обход сохраняет успешные разделы независимо, а failed section не
период независимо от TTL. Повторная сверка полного периода публикуется одной заменяет прежний complete result. Отменой query lifecycle владеет TanStack
транзакцией после всех страниц, интервалов и счетов, включая `all`. Query. Открытый экран перечитывает ресурс не чаще одного раза в 30 минут;
Сбой сохраняет весь прежний результат. Первая загрузка может публиковать это локальный HTTP read. Совместимый параметр `sync=observe`, пока он есть в
полные малые интервалы и показывать частичный период без окончательных сумм. маршруте, также является только чтением и не представляет команду обходу.
[HTTP API](../http-api.md) описывает исполняемый контракт envelope.
Клиент наблюдает только известную активную работу открытого экрана.
Status GET и data GET с `sync=observe` не запускают работу. После изменения
состояния ответ попадает в ту же query identity; после ухода или завершения
наблюдение прекращается. Поздний ответ не заменяет уже принятый новый.
[HTTP API](../http-api.md) объясняет envelope и экранный refresh.
Отменой query lifecycle владеет TanStack Query. Status не пересобирает
финансовые ответы и не передаёт hash notifications. Свечи нового диапазона
загружаются при его открытии; предзагрузка всей истории портфеля не выполняется.
## Смена подключения ## Смена подключения
+32 -20
View File
@@ -2,7 +2,8 @@
## Источник контракта ## Источник контракта
Backend генерирует OpenAPI из собственного публичного API. Frontend использует Backend генерирует OpenAPI из собственного публичного API. Этот сгенерированный
OpenAPI — исполняемый источник HTTP-контракта. Frontend использует
предоставленный OpenAPI snapshot как актуальный вход и локально генерирует предоставленный OpenAPI snapshot как актуальный вход и локально генерирует
типизированный клиент. Backend владеет контрактом, а подготовка и доставка типизированный клиент. Backend владеет контрактом, а подготовка и доставка
схемы находятся вне frontend. Это разделение принято в схемы находятся вне frontend. Это разделение принято в
@@ -20,29 +21,40 @@ artifact у себя и проверяет соответствие generated ty
API имеет prefix `/api/v1`; Swagger публикуется для локальной разработки по API имеет prefix `/api/v1`; Swagger публикуется для локальной разработки по
environment policy, а не используется frontend в runtime. environment policy, а не используется frontend в runtime.
## Скринер акций
`POST /api/v1/stocks/screener/search` всегда создаёт новый результат по
условиям скринера, включая пустой подтверждённый список. Ответ первой страницы
содержит непрозрачный `searchId`, время получения каталога и признак следующей
страницы. `GET /api/v1/stocks/screener/search/{searchId}?page=...` читает
последующую страницу того же результата, не запускает новый поиск и сохраняет
состав и время списка. Идентификатор результата принадлежит текущему пользователю
и его подключению; недоступный или чужой результат возвращает ошибку, а не
пустой список. Точные поля и статусы определяет backend-generated OpenAPI.
## Инвестиционные данные и синхронизация ## Инвестиционные данные и синхронизация
T-Bank data GET возвращают envelope `{ data, meta }`. `data` может быть `null` Затронутые GET инвестиционных ресурсов возвращают сгенерированный contract
при missing или неполном финансовом агрегате; partial ledger/candles могут `{ data, meta }`. `data` nullable: `null` означает отсутствие complete result,
содержать подтверждённые строки. `meta` разделяет availability, freshness, а подтверждённый пустой массив является available complete result. `meta`
lastSuccessfulAt, sync, coverage и состояния зависимостей. `dataRevision` независимо описывает freshness, completeness, `lastSuccessfulAt`,
описывает набор данных; пустое завершённое покрытие явно представлено в coverage. resource-relevant `lastAttempt` и availability. `lastAttempt` имеет состояния
Публичной hash-версии состояния нет. Ни одно поле не раскрывает connection revision. `none`, `running`, `succeeded`, `partial` и `failed`; его неуспех не заменяет
сохранённый complete result или его время. `Portfolio.isStale` остаётся
специфичным для snapshot полем, а не заменой состояния попытки.
Обычный GET планирует missing/stale зависимости после проверки доступа. Только Accounts дополнительно возвращает top-level `sync`: `null`, если у
GET с `sync=observe` только читает. `POST /api/v1/tbank-sync` принимает текущего подключения ещё не было часовой попытки, иначе connection-wide
валидированный screen descriptor и возвращает `202` с handle и нормализованным наблюдаемый результат. Это наблюдение, не команда. Обычный GET и retry после
scope. `GET /api/v1/tbank-sync/:id` наблюдает разрешённую работу; чужой или проверки доступа читают локальное состояние и не начинают личную работу.
прежний handle возвращает `404`. Приём работы не означает её успех. Устаревший `sync=observe`, пока он сохранён для совместимости маршрута, также
только читает. Request-started screen-sync command/status не является текущей
AS-IS моделью.
Status возвращает state/errorCode без данных ресурсов и численных progress Безопасные ошибки завершённой часовой попытки передаются в `lastAttempt` и
counters. Клиент перечитывает показанные resources через `sync=observe` во время Accounts `sync`; HTTP transport/access/input errors сохраняют Problem Details.
работы и после завершения, сохраняя generated query identity. Sync states ресурса: Старые данные при временной source failure сохраняют исходное успешное время.
`idle`, `running`, `failed`; отдельного публичного `queued` нет. Ни одно поле не раскрывает connection revision. Детали поведения —
Source failure принятой работы передаётся безопасным `meta.sync.errorCode`;
HTTP transport/access/input errors сохраняют Problem Details. Старые данные
при transient failure сохраняют исходное успешное время. Детали поведения —
[свежесть и полнота](cross-cutting/data-freshness.md). [свежесть и полнота](cross-cutting/data-freshness.md).
Envelope несовместим с прежними bare-array ответами: backend/frontend Envelope несовместим с прежними bare-array ответами: backend/frontend
+9 -1
View File
@@ -1,4 +1,12 @@
module.exports = { module.exports = {
extends: ["@commitlint/config-conventional"], extends: ["@commitlint/config-conventional"],
rules: { "type-enum": [2, "always", ["feat", "fix", "perf", "docs", "spec", "refactor", "build", "ci", "test", "style", "chore", "revert"]] }, defaultIgnores: false,
ignores: [
message => /^chore\(release\): \d+\.\d+\.\d+$/.test(message.trim()),
message => /^Merge pull request ['"].+['"] \(#\d+\) from .+ into .+$/.test(message.trim()),
],
rules: {
"type-enum": [2, "always", ["feat", "fix", "perf", "docs", "spec", "refactor", "build", "ci", "test", "style", "chore", "revert"]],
"references-empty": [2, "never"],
},
}; };
+2 -3
View File
@@ -89,9 +89,8 @@ JavaScript Number. Отдельный ввод ограничен signed64: на
следующие страницы. Баланс при выборе прошлого периода остаётся текущим. следующие страницы. Баланс при выборе прошлого периода остаётся текущим.
Сводка учитывает все подходящие записи, включая не показанные на странице. Сводка учитывает все подходящие записи, включая не показанные на странице.
Сводка одной или всех карт показывает одну итоговую сумму расходов с учётом Сводка одной или всех карт отдельно показывает расходы, возвращённую сумму и
возвратов и компактные строки категорий по убыванию итоговых расходов. Отдельные показатели «Возвращено» итог после возвратов, а также компактные строки категорий по убыванию итоговых расходов. Возврат уменьшает расходы месяца своего
и «После возвратов» в интерфейсе скрыты; расчёт и операции возврата сохранены. Возврат уменьшает расходы месяца своего
получения: августовская покупка 1 000 ₽ и сентябрьский возврат 600 ₽ дают получения: августовская покупка 1 000 ₽ и сентябрьский возврат 600 ₽ дают
августовский итог 1 000 ₽ и сентябрьский −600 ₽ при отсутствии других трат. августовский итог 1 000 ₽ и сентябрьский −600 ₽ при отсутствии других трат.
Начальный остаток, пополнения и переводы в эти показатели не входят. Начальный остаток, пополнения и переводы в эти показатели не входят.
+30 -23
View File
@@ -40,10 +40,10 @@
## Период и список ## Период и список
Без фильтра период начинается сегодня в UTC и заканчивается через 30 дней Без фильтра период начинается сегодня в UTC и заканчивается через 30 дней
после начала, обе даты включены. Поля «С» и «По» позволяют изменить период: после начала, обе даты включены. `from` и `to` принимают только строгие даты
«Применить» сохраняет выбранные календарные даты в URL и запрашивает результат, `YYYY-MM-DD`; без `from` используется текущая дата UTC, без `to` — `from + 30`
«Сбросить» возвращает период по умолчанию. Обзор счёта сохраняет прогноз календарных дней. Поля «С» и «По» сохраняют выбранные календарные даты в URL,
на текущую дату и следующие 30 дней. а «Сбросить» возвращает период по умолчанию.
События упорядочены по календарной дате. У каждой строки видны тип, События упорядочены по календарной дате. У каждой строки видны тип,
инструмент, дата и доступная сумма в исходной валюте. Список не имеет инструмент, дата и доступная сумма в исходной валюте. Список не имеет
@@ -52,10 +52,13 @@
отсутствия всех будущих выплат. Инструмент без поддерживаемых данных отсутствия всех будущих выплат. Инструмент без поддерживаемых данных
не получает искусственную строку «нет данных». не получает искусственную строку «нет данных».
API принимает необязательные `from` и `to` в формате `YYYY-MM-DD` для Сохранённый forecast сохраняет свой `calculatedAt` и исходное включительное
отдельного и общего счёта. Без `from` используется сегодня в UTC, окно. GET для отдельного счёта или `all` возвращает только пересечение этого
без `to` — 30 дней после начала. Неверный формат или несуществующая дата окна и запрошенного UTC-периода, не меняя ни `calculatedAt`, ни исходное окно.
дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`. Пустое пересечение или отсутствие событий в пересечении — успешный пустой
список с теми же metadata; это не отсутствие forecast. Неверный формат или
несуществующая дата дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`
без замены периода и без запуска личной работы.
Фильтрация на сервере предшествует сортировке и вычислению Фильтрация на сервере предшествует сортировке и вычислению
`incomeTotalsByCurrency`, включающего только купоны и дивиденды. `incomeTotalsByCurrency`, включающего только купоны и дивиденды.
Итоги остаются в ответе API; полный экран показывает список без общего итога. Итоги остаются в ответе API; полный экран показывает список без общего итога.
@@ -63,26 +66,30 @@ API принимает необязательные `from` и `to` в форма
## Получение и отказы ## Получение и отказы
Запрос требует сессии, подключения и локально подтверждённого membership. Запрос требует сессии, подключения и локально подтверждённого membership.
Прогноз строится из личного сохранённого portfolio и общих календарей: T-Bank для Он читает сохранённый forecast и не запускает личную синхронизацию. Часовой
дивидендов, MOEX для bond events. Отдельного синхронного получения portfolio обход строит forecast из полного личного portfolio и общих календарей: T-Bank
нет. Личные оценки сохраняются отдельно от общих календарей. для дивидендов, MOEX для bond events. Личные оценки сохраняются отдельно от
общих календарей.
Последний полный forecast привязан к scope, периоду и membership. Последний полный forecast привязан к scope, исходному окну и membership. Если
Если новый portfolio требует ещё недоступного календаря, прежний полный часовой обход не может получить полный новый forecast, прежний полный прогноз,
прогноз и его source times остаются, в том числе после рестарта. Новый его `calculatedAt` и исходное окно остаются читаемыми, в том числе после
полный результат заменяет его атомарно. Без fallback показывается рестарта; `meta.lastAttempt` отдельно сообщает об ошибке обновления. Без
missing/partial, а не подтверждённое отсутствие выплат. Другой период или полного forecast `data: null` и metadata обозначает initial loading либо
изменившийся membership не получают старый прогноз под новым названием. временную недоступность, а не подтверждённое отсутствие выплат. В режиме `all`
Source failure сообщается в metadata и не изменяет успешное время. результат complete только при полном вкладе каждого включённого счёта. Другой
scope или изменившийся membership не получают старый forecast под новым
названием.
Успешный ответ MOEX без запрошенного блока означает отсутствие поддерживаемых Успешный ответ MOEX без запрошенного блока означает отсутствие поддерживаемых
событий этого источника; это отличается от transport failure и повреждённого событий этого источника; это отличается от transport failure и повреждённого
формата ответа. формата ответа.
При первом открытии показан каркас заголовка и строк, без интерактивных При первом открытии без complete forecast показан каркас заголовка и строк,
заглушек. Пустой ответ сохраняет возможность изменить период. без интерактивных заглушек. Пустой успешный ответ сохраняет возможность
При обычном фоновом обновлении уже полученные данные остаются на экране, изменить период. При failed HTTP reread уже полученный Client Cached Snapshot
ошибка получает предупреждение и повторную попытку. Без выбранного счёта остаётся на экране; это отличается от server-side failed hourly attempt.
запрос не выполняется. Смена сессии и подключения следует Повторная попытка перечитывает только HTTP-ответ. Без выбранного счёта запрос
не выполняется. Смена сессии и подключения следует
[общим правилам финансовых данных](../../architecture/cross-cutting/data-freshness.md). [общим правилам финансовых данных](../../architecture/cross-cutting/data-freshness.md).
Внешние границы объясняют интеграции [T-Bank](../../integrations/tbank.md) Внешние границы объясняют интеграции [T-Bank](../../integrations/tbank.md)
+6
View File
@@ -143,3 +143,9 @@ BondBy переиспользуется зависимостями выпуск
и [проверками](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/bonds/application/bond.spec.ts). и [проверками](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/bonds/application/bond.spec.ts).
Границы источников описаны в [разделе интеграций](../../integrations/README.md), Границы источников описаны в [разделе интеграций](../../integrations/README.md),
сходное разделение рыночных и личных данных — в [акциях](stocks.md). сходное разделение рыночных и личных данных — в [акциях](stocks.md).
## Online reference
Bond detail, search, and ticker lookup are read from the upstream integration
on each request. Saved quotes, candles, events, ratings, and portfolio labels
retain their own freshness and failure boundaries.
+32 -19
View File
@@ -28,24 +28,29 @@
на frontend. Общее для акций и облигаций восстановление справочных данных на frontend. Общее для акций и облигаций восстановление справочных данных
принадлежит [загрузке портфеля на backend](../portfolio/flows/portfolio-loading.md). принадлежит [загрузке портфеля на backend](../portfolio/flows/portfolio-loading.md).
Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: поиск Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: скринер
по названию или тикеру через каталог Т-Банка, начиная с двух символов. запускается кнопкой «Найти» с необязательным названием или тикером, сектором,
Результаты разных выпусков, включая обыкновенные и привилегированные акции, типом акции, валютой расчётов, площадкой, страной риска и максимальным размером
имеют отдельные UID. Карточка результата показывает логотип, последнюю цену лота. Он использует полный полученный каталог и показывает только акции, для
с её временем, тип бумаги, площадку, код режима, ISIN и доступность торгов через которых каталог подтверждает доступность покупки и торговли через API. Это не
API. Поиск показывает одну карточку на нормализованный ISIN. До ограничения гарантирует, что конкретная заявка пользователя будет исполнена прямо сейчас.
в 30 результатов выбирается представитель выпуска: доступность через API,
точное совпадение тикера, затем режим TQBR; равные варианты упорядочены по UID. Скринер показывает одну карточку на выпуск с нормализованным ISIN, а выпуск
Записи без ISIN сохраняются отдельно по UID. Обыкновенные и привилегированные без ISIN остаётся отдельной карточкой точного UID. Обыкновенные и
акции с разными ISIN не объединяются. Цена и ссылка принадлежат выбранному привилегированные акции с разными ISIN не объединяются. После отбора карточки
UID; данные разных режимов не смешиваются. Прямые ссылки из портфеля сохраняют упорядочены по тикеру и UID, разделены на страницы по 30 и показывают единое
время получения списка. Изменение условий не заменяет текущий список до
следующего нажатия «Найти». Повторный поиск получает новый каталог; страницы
одного результата не пересчитываются. Подтверждённый пустой результат отличается
от ошибки источника, для которой интерфейс предлагает повторить поиск.
Ссылка карточки принадлежит выбранному UID; данные разных режимов не смешиваются.
Прямые ссылки из портфеля сохраняют
исходный UID, даже если поиск выбрал другой режим этого выпуска; такая страница исходный UID, даже если поиск выбрал другой режим этого выпуска; такая страница
сохраняет UUID в адресе. Если один точный тикер относится к разным выпускам, сохраняет UUID в адресе. Если один точный тикер относится к разным выпускам,
сервер возвращает `409 STOCK_TICKER_AMBIGUOUS`, а страница предлагает поиск. сервер возвращает `409 STOCK_TICKER_AMBIGUOUS`.
Поиск тикера нечувствителен к регистру, но использует точное совпадение:
SBER не заменяется на SBERP. Однобуквенные тикеры также поддерживаются.
Прямая ссылка не требует предварительного открытия портфеля. Хлебные крошки Прямая ссылка не требует предварительного открытия портфеля. Хлебные крошки
«Акции → название» возвращают к поиску. «Акции → название» возвращают к скринеру.
## Содержание и состояния ## Содержание и состояния
@@ -144,10 +149,11 @@ TTM означает последние 12 месяцев, MRQ — послед
## Получение данных и ограничения ## Получение данных и ограничения
Общие metadata, discovery, company, quotes, свечи и календари сохраняются Общие metadata, discovery, company, quotes, свечи и календари сохраняются
в SQLite. Поиск хранит подтверждённый набор UID для конкретного query; в SQLite. Скринер получает каталог online и показывает время его получения;
успешный SBER не подтверждает пустой GAZP. Отсутствующее enrichment не временная недоступность каталога не подтверждает отсутствие подходящих акций.
скрывает найденную бумагу. Сохранённые общие источники переиспользуются Отсутствующее enrichment не скрывает найденную бумагу. Сохранённые общие
между пользователями, но личные позиции и выплаты всегда проверяют доступ. источники переиспользуются между пользователями, но личные позиции и выплаты
всегда проверяют доступ.
Обычное чтение не ждёт RPC; missing/stale зависимости запрашиваются в фоне Обычное чтение не ждёт RPC; missing/stale зависимости запрашиваются в фоне
через существующий T-Bank limiter. Минутная свежесть применяется к quotes через существующий T-Bank limiter. Минутная свежесть применяется к quotes
@@ -184,3 +190,10 @@ scope. Частичные строки видны с предупреждени
[рыночным данным](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock-market.service.ts), [рыночным данным](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock-market.service.ts),
[выплатам](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock-income.service.ts) и [проверкам](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock.spec.ts). [выплатам](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock-income.service.ts) и [проверкам](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock.spec.ts).
Сопоставление с облигациями — на [странице облигаций](bonds.md). Сопоставление с облигациями — на [странице облигаций](bonds.md).
## Online reference
Stock detail, company data, search, and ticker lookup are read from the
upstream integration on each request. Saved positions, quotes, candles, and
events remain independent local resources and are not replaced by a reference
read failure.
+32 -31
View File
@@ -1,46 +1,47 @@
# Загрузка портфеля # Загрузка портфеля
Экран `/accounts/:accountId` читает последний полный snapshot из SQLite Экран `/accounts/:accountId` читает последний полный snapshot из SQLite после
после проверки сессии, подключения и локального membership. Если список проверки сессии, подключения и локального membership. Если список счетов ещё
счетов ещё неизвестен, сервер сообщает о загрузке доступа без выдачи личных неизвестен, сервер сообщает о загрузке доступа без выдачи личных данных
данных неизвестного ID. Известный недоступный счёт возвращает `404`. неизвестного ID. Известный недоступный счёт возвращает `404`.
## Основной обмен ## Основной обмен
Обычный GET возвращает локальный envelope. Missing/stale зависимости Обычный GET и retry возвращают read-only локальный `{ data, meta }` envelope:
запрашиваются в фоне; чтение не ждёт T-Bank. Для нового полного snapshot они не ждут и не вызывают T-Bank и не предлагают ручную синхронизацию. Часовой
нужны оба финансовых ответа `GetPortfolio` и `GetPositions`. Суммы и позиции обход текущего подключения обновляет Portfolio независимо от экрана. Для нового
публикуются вместе; metadata дополняет представление независимо, с доступным полного snapshot ему нужны оба финансовых ответа `GetPortfolio` и
UID/FIGI вместо имени до её загрузки. `GetPositions`; суммы и позиции публикуются вместе. Metadata инструмента
дополняет представление независимо, с доступным UID/FIGI вместо имени до её
онлайн-загрузки.
Свежесть portfolio — 60 секунд. Истечение срока не удаляет snapshot и не Открытый экран выполняет локальное перечитывание не чаще одного раза в
создаёт таймер. «Обновить» на обзоре перечитывает зависимости текущего экрана: 30 минут; retry также повторяет только HTTP GET. `data: null` означает, что
membership, portfolio, показанные операции, доход и будущие события. полного snapshot ещё нет, а не нулевой портфель. Пустой подтверждённый portfolio
Секции могут быть готовы независимо. Подробнее — остаётся available complete result. Секции могут быть готовы независимо.
[свежесть](../../../architecture/cross-cutting/data-freshness.md). Подробнее — [свежесть](../../../architecture/cross-cutting/data-freshness.md).
## Границы доступа ## Границы доступа
Публикация проверяет connection revision и attempt в той же транзакции. Публикация проверяет connection revision и attempt в той же транзакции. Замена
Замена или удаление подключения не допускает позднюю запись прежней работы. или удаление подключения не допускает позднюю запись прежней работы. Frontend
Frontend очищает недоступный personal view и отклоняет запоздалые ответы. очищает недоступный personal view и отклоняет запоздалые ответы. В режиме
В режиме [«Все счета»](../all-accounts.md#полнота-свежесть-и-доступ) состав [«Все счета»](../all-accounts.md#полнота-свежесть-и-доступ) состав accounts и
accounts и snapshots читается согласованно, но их source times могут различаться. snapshots читается согласованно, но их source times могут различаться.
## Ошибки и результат для пользователя ## Ошибки и результат для пользователя
Нет подключения — `409 TBANK_NOT_CONNECTED`, известный отказ токена — Нет подключения — `409 TBANK_NOT_CONNECTED`, известный отказ токена —
`400 INVALID_TBANK_TOKEN`, недоступный счёт — `404`. Они не маскируются `400 INVALID_TBANK_TOKEN`, недоступный счёт — `404`. Они не маскируются
запасным snapshot. Transient source failure оставляет прежний полный портфель запасным snapshot. Временная ошибка часового обхода оставляет прежний полный
и его исходное время с безопасным предупреждением. При отсутствии snapshot portfolio и его исходное `lastSuccessfulAt`; `meta.lastAttempt` сообщает о
показывается missing/failed, без нулевых итогов. `503` означает ошибку failed или partial попытке отдельно. `Portfolio.isStale` сообщает возраст
обслуживания HTTP-запроса, а не принятой фоновой работы. snapshot, а Client Cached Snapshot и ошибка браузерного HTTP-перечитывания
имеют независимый смысл. При отсутствии полного snapshot `data: null` и
metadata обозначает initial loading либо временную недоступность, без нулевых
итогов. `503` означает ошибку обслуживания самого HTTP-запроса, а не
завершившуюся фоновую работу.
Observer запрашивает статус известной работы, затем `sync=observe` читает Денежные правила находятся в [справочнике](../data-reference.md), проверка
изменившийся ресурс без запуска синхронизации. При уходе и terminal outcome расхождения — в [диагностике](../how-to/investigate-discrepancy.md), RPC/лимиты
наблюдение прекращается. Повторное открытие может запросить недостающее; — в [интеграции T-Bank](../../../integrations/tbank.md).
после рестарта сохранённый snapshot доступен сразу.
Денежные правила находятся в [справочнике](../data-reference.md),
проверка расхождения — в [диагностике](../how-to/investigate-discrepancy.md),
RPC/лимиты — в [интеграции T-Bank](../../../integrations/tbank.md).
+17
View File
@@ -128,6 +128,14 @@ Instrument обогащают отображение Position или Event, но
_Не использовать_: бумага, тикер, актив позиции. _Не использовать_: бумага, тикер, актив позиции.
## Скринер акций
Подбор выпусков акций по заданным условиям из каталога T-Bank с указанием
времени получения списка. Скринер отличается от текстового поиска конкретного
инструмента, личного портфеля и подтверждения исполнимости сделки.
_Не использовать_: гарантия покупки, личная проверка доступа к сделке.
## Instrument Logo ## Instrument Logo
Имя файла бренда T-Bank для отображения Instrument в интерфейсе; Имя файла бренда T-Bank для отображения Instrument в интерфейсе;
@@ -152,6 +160,15 @@ _Не использовать_: валютная позиция, заблоки
_Не использовать_: история портфеля, snapshot для графика. _Не использовать_: история портфеля, snapshot для графика.
## Точка истории стоимости портфеля
Полная оценка одного Brokerage Account в одной валюте на момент успешного
обновления Portfolio; последовательность таких точек описывает изменение
оценки во времени, включая неторговые дни. Не является Portfolio Snapshot
или инвестиционной доходностью; отсутствие цены позиции не приравнивается к нулю.
_Не использовать_: снимок состава портфеля, доходность.
## Client Cached Snapshot ## Client Cached Snapshot
Технический термин: последний успешно полученный frontend-ответ React Query, который остаётся Технический термин: последний успешно полученный frontend-ответ React Query, который остаётся
+12 -1
View File
@@ -20,6 +20,12 @@ T-Bank определяет исходные данные и права token. B
сессию, выбирает подключение её пользователя и устанавливает доступ к счёту. сессию, выбирает подключение её пользователя и устанавливает доступ к счёту.
Наличие идентификатора счёта в URL этого доступа не подтверждает. Наличие идентификатора счёта в URL этого доступа не подтверждает.
Скринер акций получает полный online-каталог акций T-Bank для каждого нового
поиска. В него входят только инструменты, для которых каталог подтверждает и
доступность покупки, и торговли через API. Эти признаки описывают полученный
снимок каталога: они не подтверждают личные права пользователя, состояние торгов
или исполнение будущей заявки. Скринер не использует личный портфель как каталог.
[MOEX](moex.md) и [НКР](nkr.md) дополняют публичные сведения об облигациях; они не заменяют [MOEX](moex.md) и [НКР](nkr.md) дополняют публичные сведения об облигациях; они не заменяют
брокера как источник личных позиций и исполненных выплат. Границы источников брокера как источник личных позиций и исполненных выплат. Границы источников
показаны в [контексте](../architecture/context.md), смысл дополнений — в показаны в [контексте](../architecture/context.md), смысл дополнений — в
@@ -91,7 +97,12 @@ sequenceDiagram
`INVALID_TBANK_TOKEN` означает отказ внешней аутентификации или прав доступа. `INVALID_TBANK_TOKEN` означает отказ внешней аутентификации или прав доступа.
`TBANK_UNAVAILABLE` сообщает о временной или иной upstream-ошибке, включая `TBANK_UNAVAILABLE` сообщает о временной или иной upstream-ошибке, включая
исчерпание очереди. Ответы и ошибки не содержат token. Удаление подключения исчерпание очереди. Диагностические причины жизненного цикла часовой попытки
(`INTERRUPTED` — прерывание до нормального завершения, `DEADLINE` — истечение
ограничения ожидания шага) не относятся к ошибкам T-Bank: они остаются
внутренней диагностикой и не раскрываются в hourly-read. Истечение ограничения
ожидания не отменяет уже начатые обращения к T-Bank; их поздние результаты
остаются в строках шагов. Ответы и ошибки не содержат token. Удаление подключения
идемпотентно: удаляются локальный секрет, личные datasets и work; поздняя идемпотентно: удаляются локальный секрет, личные datasets и work; поздняя
публикация прежней revision запрещена. Общие неперсональные источники могут публикация прежней revision запрещена. Общие неперсональные источники могут
сохраняться. Оно не описывает отзыв token на стороне T-Bank. сохраняться. Оно не описывает отзыв token на стороне T-Bank.
+1 -1
View File
@@ -24,7 +24,7 @@ WealthLedger — локальное приложение для частного
| Посчитать полученные выплаты | [Пассивный доход](domains/income/overview.md): исполненные купоны и дивиденды за календарный период | | Посчитать полученные выплаты | [Пассивный доход](domains/income/overview.md): исполненные купоны и дивиденды за календарный период |
| Посмотреть ожидаемые события | [Будущие выплаты](domains/income/upcoming-events.md): купоны, дивиденды, погашения и оферты по текущим позициям | | Посмотреть ожидаемые события | [Будущие выплаты](domains/income/upcoming-events.md): купоны, дивиденды, погашения и оферты по текущим позициям |
| Увидеть общий состав инвестиций | Режим [«Все счета»](domains/portfolio/all-accounts.md), сохраняющий принадлежность строк к счетам | | Увидеть общий состав инвестиций | Режим [«Все счета»](domains/portfolio/all-accounts.md), сохраняющий принадлежность строк к счетам |
| Изучить конкретный инструмент | Поиск и страницы [акций](domains/instruments/stocks.md) и [облигаций](domains/instruments/bonds.md): рынок, личная позиция, история и события | | Изучить конкретный инструмент | [Скринер акций](domains/instruments/stocks.md) по параметрам каталога, страницы акций и поиск [облигаций](domains/instruments/bonds.md): рынок, личная позиция, история и события |
## Как связаны представления ## Как связаны представления
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "wealth-ledger-docs", "name": "wealth-ledger-docs",
"version": "0.1.3", "version": "0.1.4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "wealth-ledger-docs", "name": "wealth-ledger-docs",
"version": "0.1.3", "version": "0.1.4",
"devDependencies": { "devDependencies": {
"@commitlint/cli": "21.2.2", "@commitlint/cli": "21.2.2",
"@commitlint/config-conventional": "21.2.2", "@commitlint/config-conventional": "21.2.2",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "wealth-ledger-docs", "name": "wealth-ledger-docs",
"version": "0.1.3", "version": "0.1.4",
"private": true, "private": true,
"engines": { "engines": {
"node": "24.21.0" "node": "24.21.0"