Compare commits
3
Commits
v0.1.5
..
fab9e5b30d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fab9e5b30d | ||
|
|
a45d3e77b9 | ||
|
|
3a272681c5 |
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug Report
|
|
||||||
about: Неверное поведение
|
|
||||||
---
|
|
||||||
# Bug Report
|
|
||||||
|
|
||||||
## Проблема и шаги воспроизведения
|
|
||||||
|
|
||||||
## Факт / ожидание
|
|
||||||
|
|
||||||
## Acceptance Criteria
|
|
||||||
|
|
||||||
- [ ]
|
|
||||||
|
|
||||||
## Окружение / ссылки (если применимо)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
name: Engineering Task
|
|
||||||
about: CI, тесты, документация, процесс и прочее
|
|
||||||
---
|
|
||||||
# Engineering Task
|
|
||||||
|
|
||||||
## Контекст и результат
|
|
||||||
|
|
||||||
## Scope / связанные Issues (если есть)
|
|
||||||
|
|
||||||
## Acceptance Criteria
|
|
||||||
|
|
||||||
- [ ]
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature Request
|
|
||||||
about: Новое наблюдаемое поведение
|
|
||||||
---
|
|
||||||
# Feature Request
|
|
||||||
|
|
||||||
## Зачем и какой результат
|
|
||||||
|
|
||||||
## Ожидаемое поведение
|
|
||||||
|
|
||||||
## Acceptance Criteria
|
|
||||||
|
|
||||||
- [ ]
|
|
||||||
|
|
||||||
## Зависимости / связанные Issues (если есть)
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
name: Refactoring / Technical Debt
|
|
||||||
about: Улучшение без нового поведения
|
|
||||||
---
|
|
||||||
# Refactoring / Technical Debt
|
|
||||||
|
|
||||||
## Проблема и результат
|
|
||||||
|
|
||||||
## Сохраняемые инварианты / границы
|
|
||||||
|
|
||||||
## Acceptance Criteria
|
|
||||||
|
|
||||||
- [ ]
|
|
||||||
|
|
||||||
## Зависимости / ссылки (если есть)
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Pull Request
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Краткий результат работы описывается здесь.
|
|
||||||
|
|
||||||
## Linked Issue
|
|
||||||
|
|
||||||
Refs `<owner/repo#number>` (заменить ссылкой на реальную Issue).
|
|
||||||
|
|
||||||
## Changes
|
|
||||||
|
|
||||||
Затронутые части и изменения.
|
|
||||||
|
|
||||||
## Verification
|
|
||||||
|
|
||||||
- Команда / результат / ограничения:
|
|
||||||
|
|
||||||
## Breaking Changes (если есть)
|
|
||||||
@@ -4,10 +4,6 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened, edited]
|
types: [opened, synchronize, reopened, edited]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: docs-commits-${{ gitea.event.pull_request.number }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
commits:
|
commits:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -27,8 +23,4 @@ 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
|
|
||||||
|
|||||||
@@ -2,16 +2,12 @@ name: Docs security
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [develop, main]
|
branches:
|
||||||
|
- '**'
|
||||||
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
|
||||||
|
|||||||
@@ -2,13 +2,8 @@ name: Docs verify
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [develop, main]
|
branches: ['**']
|
||||||
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:
|
||||||
|
|||||||
@@ -3,9 +3,6 @@
|
|||||||
Перед изменением прочитай [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;
|
||||||
внешние источники используй как справочные свидетельства, когда они доступны.
|
внешние источники используй как справочные свидетельства, когда они доступны.
|
||||||
@@ -23,13 +20,7 @@
|
|||||||
|
|
||||||
## Ветки и релизы
|
## Ветки и релизы
|
||||||
|
|
||||||
Работа — в issue-linked ветке от `develop`, затем PR в `develop`; в `main` напрямую
|
Работа — в отдельной ветке от `develop`, затем PR в `develop`; в `main` напрямую
|
||||||
не пушить. PR сливается squash или rebase-merge; merge-коммит не используется.
|
не пушить. Release/hotfix и синхронизация веток — по [README](README.md#релизы).
|
||||||
`main` обновляется только fast-forward из `develop`, поэтому `origin/main`
|
Commits и заголовки PR — Conventional Commits; для спецификаций допустим `spec:`.
|
||||||
всегда предок `origin/develop`:
|
|
||||||
`git merge-base --is-ancestor origin/main origin/develop`. Срочный fix —
|
|
||||||
обычная ветка `fix/*` от `develop`; пути hotfix от `main` нет.
|
|
||||||
Релиз — по [README](README.md#релизы).
|
|
||||||
Commits и заголовки PR — Conventional Commits со ссылкой на Issue (кроме release);
|
|
||||||
для спецификаций допустим `spec:`.
|
|
||||||
Перед подготовкой релиза прочитай местный README; версии вручную не повышать.
|
Перед подготовкой релиза прочитай местный README; версии вручную не повышать.
|
||||||
|
|||||||
@@ -1,48 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [0.1.5](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.4...v0.1.5) (2026-10-18)
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
* align current pages with hourly freshness model (WealthLedger/docs[#34](https://git.personal.ksv741.ru/WealthLedger/docs/issues/34)) ([#42](https://git.personal.ksv741.ru/WealthLedger/docs/issues/42)) ([7b61eb8](https://git.personal.ksv741.ru/WealthLedger/docs/commit/7b61eb8e6ba93a765b1ae27ca31d77b5e422e149))
|
|
||||||
* describe ASCII 8-72 password policy and drop resolved discrepancy (WealthLedger/docs[#46](https://git.personal.ksv741.ru/WealthLedger/docs/issues/46)) ([#47](https://git.personal.ksv741.ru/WealthLedger/docs/issues/47)) ([56885f4](https://git.personal.ksv741.ru/WealthLedger/docs/commit/56885f450bc1298d383d496174d16e591926e047))
|
|
||||||
* describe events default period and picker bounds (WealthLedger/frontend[#63](https://git.personal.ksv741.ru/WealthLedger/docs/issues/63)) ([8a2a62c](https://git.personal.ksv741.ru/WealthLedger/docs/commit/8a2a62c611e1acc1c1e69048a88b049bbf0d9087))
|
|
||||||
* describe quiet reading and visible source state ([#51](https://git.personal.ksv741.ru/WealthLedger/docs/issues/51)) ([e8e3ef6](https://git.personal.ksv741.ru/WealthLedger/docs/commit/e8e3ef62854dae8448deaa66ac26e5b15d5c7d6a))
|
|
||||||
* document income without comparisons and unified payouts (WealthLedger/main[#33](https://git.personal.ksv741.ru/WealthLedger/docs/issues/33)) ([#40](https://git.personal.ksv741.ru/WealthLedger/docs/issues/40)) ([03fb045](https://git.personal.ksv741.ru/WealthLedger/docs/commit/03fb045a9ee8a36775599bda66e7f6a08362bd84))
|
|
||||||
* document Nexus delivery with shared account (WealthLedger/docs[#18](https://git.personal.ksv741.ru/WealthLedger/docs/issues/18)) ([#48](https://git.personal.ksv741.ru/WealthLedger/docs/issues/48)) ([550143a](https://git.personal.ksv741.ru/WealthLedger/docs/commit/550143aea1f0ac90630f326dd927091b0ec4f38e))
|
|
||||||
|
|
||||||
### CI
|
|
||||||
|
|
||||||
* rerun commits proof on PR title edit (WealthLedger/docs[#35](https://git.personal.ksv741.ru/WealthLedger/docs/issues/35)) ([03110e9](https://git.personal.ksv741.ru/WealthLedger/docs/commit/03110e99ea58600bacd4c091fda8591d374a5a8d))
|
|
||||||
|
|
||||||
### Maintenance
|
|
||||||
|
|
||||||
* adopt linear git model in docs instructions ([#49](https://git.personal.ksv741.ru/WealthLedger/docs/issues/49)) ([11f819e](https://git.personal.ksv741.ru/WealthLedger/docs/commit/11f819ed31226a05524ac35a893064525713e41b))
|
|
||||||
|
|
||||||
## [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
|
||||||
|
|||||||
@@ -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,60 +72,35 @@ WealthLedger помогает частному инвестору понимат
|
|||||||
## Релизы
|
## Релизы
|
||||||
|
|
||||||
Репозиторий выпускается независимо. `develop` — интеграция, `main` — принятые
|
Репозиторий выпускается независимо. `develop` — интеграция, `main` — принятые
|
||||||
релизы. Обычная работа: issue-linked ветка от актуального `develop`, PR в `develop`;
|
релизы. Работа: `codex/<task>` от актуального `develop`, PR в `develop`.
|
||||||
общие правила — в Engineering Workflow по ссылке из AGENTS.
|
Обычные PR допускают squash; release и обратная синхронизация сохраняют историю.
|
||||||
PR сливается squash или rebase-merge; merge-коммит не используется. `main`
|
Commits и PR titles — Conventional Commits, включая `spec:`. Версии вручную не повышай.
|
||||||
обновляется только fast-forward из `develop`, поэтому история линейна:
|
|
||||||
|
|
||||||
```text
|
1. Получи `main`, `develop` и теги: `git fetch origin --tags`. Убедись, что
|
||||||
<type>/<issue>-<slug> --squash--> develop --ff-only--> main --> tag vX.Y.Z
|
`develop` содержит последний релиз. Создай `release/<name>` от проверенного
|
||||||
```
|
`develop`; `nvm use --silent`, `npm ci`. Hotfix начинается от `main` в
|
||||||
|
`release/hotfix-<name>` и проходит тот же процесс.
|
||||||
Инвариант: `origin/main` всегда предок `origin/develop`. Проверка:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git fetch -q origin
|
|
||||||
git merge-base --is-ancestor origin/main origin/develop && echo ok || echo BROKEN
|
|
||||||
```
|
|
||||||
|
|
||||||
Commits и PR titles — Conventional Commits со ссылкой на Issue (кроме release),
|
|
||||||
включая `spec:`. Версии вручную не повышай.
|
|
||||||
|
|
||||||
1. Получи `main`, `develop` и теги: `git fetch origin --tags`. Проверь
|
|
||||||
инвариант. Создай `release/X.Y.Z` от проверенного `develop`;
|
|
||||||
`nvm use --silent`, `npm ci`.
|
|
||||||
2. На чистой ветке выполни `npm run release:preview`, просмотри версию/changelog,
|
2. На чистой ветке выполни `npm run release:preview`, просмотри версию/changelog,
|
||||||
затем `npm run release:prepare`. Команда создаёт `chore(release): X.Y.Z`,
|
затем `npm run release:prepare`. Команда создаёт `chore(release): X.Y.Z`,
|
||||||
обновляет manifest/lockfile/CHANGELOG; тег и push не выполняет. Не обходи
|
обновляет manifest/lockfile/CHANGELOG; тег и push не выполняет. Не обходи
|
||||||
guards ветки, чистого дерева, отсутствующих тегов или уже подготовленной версии.
|
guards ветки, чистого дерева, отсутствующих тегов или уже подготовленной версии.
|
||||||
3. Проверь diff и штатные gates этого репозитория. Отправь только release-ветку,
|
3. Проверь diff и штатные gates этого репозитория. Отправь только release-ветку,
|
||||||
открой PR в **`develop`** с заголовком `chore(release): X.Y.Z`. После зелёных
|
открой PR в `main` с заголовком `chore(release): X.Y.Z`. После зелёных
|
||||||
`verify`, `security`, `commits` выполни fast-forward-only merge. Если
|
`verify`, `security`, `commits` выполни fast-forward-only merge. Если `main`
|
||||||
`develop` изменился, обнови release-ветку и повтори проверки кандидата.
|
изменился, согласуй историю и повтори проверки кандидата.
|
||||||
4. Открой PR `develop → main` с тем же заголовком и слей fast-forward-only.
|
4. Получи удалённый `main`, сравни его HEAD с проверенным release SHA и версией
|
||||||
5. Получи удалённый `main`, сравни его HEAD с проверенным release SHA и версией
|
|
||||||
manifest/lockfile. Создай аннотированный `vX.Y.Z` именно на этом SHA:
|
manifest/lockfile. Создай аннотированный `vX.Y.Z` именно на этом SHA:
|
||||||
`git tag -a vX.Y.Z <release-sha> -m "Release X.Y.Z"`, затем отправь только
|
`git tag -a vX.Y.Z <release-sha> -m "Release X.Y.Z"`, затем отправь только
|
||||||
`git push origin refs/tags/vX.Y.Z`. Не запускай release-it повторно на `main`.
|
`git push origin refs/tags/vX.Y.Z`. Не запускай release-it повторно на `main`.
|
||||||
|
5. Верни release-коммит через PR `main → develop` без squash/rebase; проверь,
|
||||||
Обратная синхронизация не нужна: release-коммит попал в `develop` на шаге 3.
|
что `develop` содержит тег. Опубликованные теги не перемещай. При сбое после
|
||||||
Опубликованные теги не перемещай. При сбое после merge создай отсутствующий тег
|
merge создай отсутствующий тег без нового bump; до merge исправь и проверь
|
||||||
без нового bump; до merge исправь и проверь существующий кандидат без
|
существующий кандидат без повторного повышения версии.
|
||||||
повторного повышения версии.
|
|
||||||
|
|
||||||
Freeze релиза не поддерживается: пока открыт релизный PR, `develop` не двигают.
|
|
||||||
Срочный fix — обычная ветка `fix/*` от `develop` с последующим релизом;
|
|
||||||
пути от `main` нет, он сделал бы `main` не-предком `develop`. Исключение
|
|
||||||
требует явного решения: `release/hotfix-<name>` от `main`, PR в `main`, тег,
|
|
||||||
затем merge `main → develop` для восстановления инварианта.
|
|
||||||
|
|
||||||
`feat:` повышает minor, `fix:`/`perf:` и прочие разрешённые типы — patch;
|
`feat:` повышает minor, `fix:`/`perf:` и прочие разрешённые типы — patch;
|
||||||
`!`/`BREAKING CHANGE:` — major, включая версии до 1.0. `chore(release):`
|
`!`/`BREAKING CHANGE:` — major, включая версии до 1.0. `chore(release):`
|
||||||
исключён из рекомендации и changelog. Конфигурация — `.release-it.json`.
|
исключён из рекомендации и changelog. Конфигурация — `.release-it.json`.
|
||||||
В Gitea для `main`/`develop` должны быть запрещены прямой/force push и обход
|
В Gitea для `main`/`develop` должны быть запрещены прямой/force push и обход
|
||||||
администратором, включена блокировка устаревшей ветки, обязательны `verify`,
|
администратором, обязательны `verify`, `security`, `commits`; теги `v*` защищены.
|
||||||
`security`, `commits`; теги `v*` защищены. Линейность обеспечивают merge styles
|
|
||||||
репозитория: merge-коммиты и rebase `--no-ff` выключены, доступны squash,
|
|
||||||
rebase-merge и fast-forward-only; стиль по умолчанию — squash.
|
|
||||||
Workflow сам не включает эти настройки. Отдельное review approval для одного
|
Workflow сам не включает эти настройки. Отдельное review approval для одного
|
||||||
владельца не требуется. Npm publishing, deploy и Gitea Releases не включены.
|
владельца не требуется. Npm publishing, deploy и Gitea Releases не включены.
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
# 021. Тихое чтение и редкие подтверждения
|
|
||||||
|
|
||||||
**Status:** Accepted. Заменяет manual-refresh часть
|
|
||||||
[ADR 019](019-hourly-reads-and-online-instrument-reference.md) на стороне
|
|
||||||
интерфейса и уточняет клиентскую часть
|
|
||||||
[ADR 007](007-react-query-fetch-policy.md). Не меняет владельцев обновления
|
|
||||||
и границы чтения из ADR 019.
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
Экраны просмотра перекладывали на пользователя контроль над получением данных:
|
|
||||||
кнопки «Обновить» и «Повторить», индикатор фонового обновления и сообщение
|
|
||||||
о неудачной синхронизации повторялись в разных разделах. Пользователь приходит
|
|
||||||
смотреть финансы, а не обслуживать загрузку; восстановление после временного
|
|
||||||
сбоя не должно зависеть от нажатия кнопки.
|
|
||||||
|
|
||||||
При этом состояние самих данных остаётся значимым: время последнего успешного
|
|
||||||
результата источника, устаревание и исход часовой попытки влияют на доверие
|
|
||||||
к показанным суммам и не могут быть просто скрыты.
|
|
||||||
|
|
||||||
## Decision
|
|
||||||
|
|
||||||
- Автоматическое чтение клиента не сообщает о себе. Экраны просмотра не
|
|
||||||
показывают кнопок ручного обновления и повтора, индикаторов фонового
|
|
||||||
перечитывания и технических предупреждений о собственном запросе.
|
|
||||||
- Временные сбои GET восстанавливаются сами: ограниченный срок ожидания запроса
|
|
||||||
и не более двух повторов с возрастающими паузами, затем возврат к штатной
|
|
||||||
работе при появлении результата. Пользователь не инициирует восстановление.
|
|
||||||
- Состояние источника из `meta` остаётся видимым. Время последнего успешного
|
|
||||||
результата, признак устаревания, исход последней часовой попытки и неполнота
|
|
||||||
показываются текстом либо доступно именованным элементом, а не только цветом.
|
|
||||||
Это свойство данных, а не отчёт о техническом процессе, и оно не превращается
|
|
||||||
в действие пользователя.
|
|
||||||
- Доступный результат сохраняется при обновлении и временной ошибке. Неполнота
|
|
||||||
и подтверждённая пустота остаются различимыми: неизвестная сумма не становится
|
|
||||||
нулём, незавершённый расчёт не выдаётся за окончательный, незагруженный список
|
|
||||||
не выдаётся за отсутствие записей.
|
|
||||||
- Первичное ожидание ограничено по времени и показывает структуру будущего
|
|
||||||
содержимого. По его истечении экран переходит в спокойную локальную
|
|
||||||
недоступность вместо бесконечной загрузки и сам заменяет её содержимым после
|
|
||||||
восстановления. Сбой одного блока не скрывает остальные доступные блоки.
|
|
||||||
- Ошибки явных действий пользователя сохраняются и остаются видимыми. Решение
|
|
||||||
касается только чтения; отправка формы, изменение данных и сброс фильтра
|
|
||||||
по-прежнему сообщают результат, в том числе неуспешный.
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
|
|
||||||
Пользователь не может ускорить обновление вручную: нормальным владельцем
|
|
||||||
обновления остаётся часовой обход из ADR 019, и отсутствие кнопки не меняет его
|
|
||||||
срок. Если источник недоступен долго, экран показывает прежние данные с
|
|
||||||
обозначением устаревания, а не приглашение повторить.
|
|
||||||
|
|
||||||
Автоматический повтор ограничен: он покрывает короткие сетевые сбои, но не
|
|
||||||
длительную недоступность. Ошибки доступа, домена и отмены не повторяются,
|
|
||||||
mutations не повторяются вовсе.
|
|
||||||
|
|
||||||
Состояние источника и состояние клиентского чтения описывают разные вещи и
|
|
||||||
не подменяют друг друга. `Portfolio.isStale` сохраняет смысл возраста снимка;
|
|
||||||
ошибка клиентского перечитывания его не меняет.
|
|
||||||
|
|
||||||
Детали поведения — в
|
|
||||||
[ожидании и восстановлении интерфейса](../architecture/cross-cutting/ui-resilience.md)
|
|
||||||
и [свежести данных](../architecture/cross-cutting/data-freshness.md).
|
|
||||||
Согласованные требования принадлежат workspace-спецификациям
|
|
||||||
`frontend-user-feedback`, `frontend-data-resilience` и
|
|
||||||
`frontend-loading-presentation`.
|
|
||||||
@@ -25,4 +25,3 @@
|
|||||||
- [018 — Минимальная runtime-координация](018-minimal-runtime-coordination.md)
|
- [018 — Минимальная runtime-координация](018-minimal-runtime-coordination.md)
|
||||||
- [019 — Часовой обход и онлайн-справочник инструментов](019-hourly-reads-and-online-instrument-reference.md)
|
- [019 — Часовой обход и онлайн-справочник инструментов](019-hourly-reads-and-online-instrument-reference.md)
|
||||||
- [020 — Evidence for hourly sync read boundaries](020-hourly-sync-verification-evidence.md)
|
- [020 — Evidence for hourly sync read boundaries](020-hourly-sync-verification-evidence.md)
|
||||||
- [021 — Тихое чтение и редкие подтверждения](021-quiet-reading-and-rare-confirmations.md)
|
|
||||||
|
|||||||
@@ -140,15 +140,12 @@ membership текущей revision перед каждым финансовым
|
|||||||
личные данные. Ротация refresh token остаётся атомарной.
|
личные данные. Ротация refresh token остаётся атомарной.
|
||||||
|
|
||||||
SQLite хранит полный последний portfolio, операции и их подтверждённые
|
SQLite хранит полный последний portfolio, операции и их подтверждённые
|
||||||
диапазоны, private прогнозы, сохранённые точки истории оценки, общие
|
диапазоны, private прогнозы, общие instrument/market sources и intent/staging.
|
||||||
instrument/market sources и intent/staging.
|
|
||||||
Нормализованные финансовые значения сохраняются decimal-строками. Полнота
|
Нормализованные финансовые значения сохраняются decimal-строками. Полнота
|
||||||
отделена от свежести и пагинации. Ответ не ждёт внешних RPC; обновлением
|
отделена от свежести и пагинации. Ответ не ждёт внешних RPC; запрос при
|
||||||
личных данных владеет часовой обход в том же backend process через
|
необходимости запускает работу в том же backend process через существующий
|
||||||
существующий лимитер, недостающие общие источники он же ставит в фоновую
|
лимитер. На startup импорт не запускается; восстановление требует следующего
|
||||||
очередь. На startup обход начинает следующую попытку по обычному часовому
|
запроса. Подробности — [модель свежести](cross-cutting/data-freshness.md).
|
||||||
сроку; после нового подключения первая попытка начинается сразу.
|
|
||||||
Подробности — [модель свежести](cross-cutting/data-freshness.md).
|
|
||||||
|
|
||||||
PUT подключения сначала проверяет token у T-Bank, затем одной транзакцией
|
PUT подключения сначала проверяет token у T-Bank, затем одной транзакцией
|
||||||
сохраняет encrypted token, новую revision и проверенный membership.
|
сохраняет encrypted token, новую revision и проверенный membership.
|
||||||
@@ -198,8 +195,9 @@ access token и вращаемый refresh token. [Политика query-кэш
|
|||||||
|
|
||||||
Авторизация доступа, недопущение token в публичный ответ и атомарность
|
Авторизация доступа, недопущение token в публичный ответ и атомарность
|
||||||
ротации сессии — отдельные свойства; наличие типизированного клиента
|
ротации сессии — отдельные свойства; наличие типизированного клиента
|
||||||
не доказывает их. Действующий формат ошибок описан в
|
не доказывает их. Известное расхождение регистрации отмечено в
|
||||||
[HTTP API](http-api.md#error-contract).
|
[аутентификации](../domains/authentication/overview.md#регистрация-и-вход),
|
||||||
|
а действующий формат ошибок описан в [HTTP API](http-api.md#error-contract).
|
||||||
|
|
||||||
Поддерживается локальный Compose и ограниченная single-server topology с SQLite.
|
Поддерживается локальный Compose и ограниченная single-server topology с SQLite.
|
||||||
Origin браузера, адрес API и cookie policy должны быть согласованы.
|
Origin браузера, адрес API и cookie policy должны быть согласованы.
|
||||||
|
|||||||
@@ -29,14 +29,6 @@ completeness, `lastSuccessfulAt`, `lastAttempt` и availability. Первые,
|
|||||||
результату. `lastAttempt` описывает относящуюся к ресурсу часовую попытку:
|
результату. `lastAttempt` описывает относящуюся к ресурсу часовую попытку:
|
||||||
`none`, `running`, `succeeded`, `partial` или `failed`.
|
`none`, `running`, `succeeded`, `partial` или `failed`.
|
||||||
|
|
||||||
Итог попытки выводится из фактических результатов её шагов: попытка, не
|
|
||||||
завершившая обязательный шаг, не обозначается полным успехом, а полученные
|
|
||||||
успешные результаты сохраняются. Ожидание каждого шага ограничено; зависший
|
|
||||||
шаг учитывается проблемным, а начатое обращение к T-Bank не отменяется.
|
|
||||||
Попытка, потерявшая выполнение после сбоя сохранения или остановки процесса,
|
|
||||||
закрывается частичным успехом либо неуспехом и не блокирует следующий обход
|
|
||||||
дольше обычного часового срока.
|
|
||||||
|
|
||||||
Поздняя неуспешная или частичная попытка сохраняет прежний полный результат и
|
Поздняя неуспешная или частичная попытка сохраняет прежний полный результат и
|
||||||
его исходное время. Если полного результата нет, `data` равно `null`: состояние
|
его исходное время. Если полного результата нет, `data` равно `null`: состояние
|
||||||
availability объясняет первоначальную загрузку, временную недоступность либо
|
availability объясняет первоначальную загрузку, временную недоступность либо
|
||||||
|
|||||||
@@ -16,17 +16,11 @@
|
|||||||
пока неизвестно, доступен public или protected маршрут. При загрузке
|
пока неизвестно, доступен public или protected маршрут. При загрузке
|
||||||
отложенного маршрута уже доступный каркас остаётся видимым.
|
отложенного маршрута уже доступный каркас остаётся видимым.
|
||||||
|
|
||||||
Фоновое чтение не сообщает о себе: оно сохраняет видимые данные без индикации
|
Фоновое обновление и действие пользователя сохраняют видимые данные или
|
||||||
процесса и без технического предупреждения. В частности,
|
элемент управления с компактной индикацией процесса. В частности,
|
||||||
[клиентский снимок](data-freshness.md#клиентский-и-серверный-снимки) счетов или
|
[клиентский снимок](data-freshness.md#клиентский-и-серверный-снимки) счетов или
|
||||||
портфеля остаётся доступным после ошибки refetch, и эта ошибка не означает
|
портфеля остаётся доступным после ошибки refetch; сообщение и повтор
|
||||||
отсутствие инвестиций. Действие пользователя сохраняет видимые данные или
|
относятся к обновлению, а не к отсутствию инвестиций.
|
||||||
элемент управления и сообщает свой результат, включая неуспешный.
|
|
||||||
|
|
||||||
Первичное ожидание ограничено по времени. По его истечении область переходит
|
|
||||||
в спокойную локальную недоступность вместо бесконечной загрузки и сама
|
|
||||||
заменяет её содержимым после восстановления. Решение принято в
|
|
||||||
[ADR 021](../../adr/021-quiet-reading-and-rare-confirmations.md).
|
|
||||||
|
|
||||||
Серверная полнота не выводится из query lifecycle. Missing показывает
|
Серверная полнота не выводится из query lifecycle. Missing показывает
|
||||||
skeleton только отсутствующих секций, partial — подтверждённые строки и
|
skeleton только отсутствующих секций, partial — подтверждённые строки и
|
||||||
@@ -34,30 +28,20 @@ skeleton только отсутствующих секций, partial — по
|
|||||||
готовятся независимо. Только complete empty означает отсутствие операций.
|
готовятся независимо. Только complete empty означает отсутствие операций.
|
||||||
Время источника не заменяется временем получения HTTP-ответа.
|
Время источника не заменяется временем получения HTTP-ответа.
|
||||||
|
|
||||||
Экраны просмотра не предлагают ручное обновление или повтор чтения: временные
|
Ручное обновление сохраняет показанный результат и applied filters; кнопка
|
||||||
сбои GET восстанавливаются сами ограниченным числом повторов, сохраняя
|
недоступна во время уже запрошенной работы. Ошибка transport отличается от
|
||||||
показанный результат и applied filters. Ошибка transport отличается от
|
|
||||||
ошибки source work. Status observation прекращается после terminal outcome
|
ошибки source work. Status observation прекращается после terminal outcome
|
||||||
или ухода; само истечение TTL не запускает импорт. Известный access loss
|
или ухода; само истечение TTL не запускает импорт. Известный access loss
|
||||||
очищает personal view, включая защиту от позднего ответа.
|
очищает personal view, включая защиту от позднего ответа.
|
||||||
|
|
||||||
Состояние источника при этом видимо: время последнего успешного результата,
|
|
||||||
устаревание, исход последней часовой попытки и неполнота показаны текстом либо
|
|
||||||
доступно именованным элементом рядом с данными, к которым относятся. Это
|
|
||||||
свойство данных, а не отчёт о техническом процессе, и оно не требует действия.
|
|
||||||
|
|
||||||
## Известная ошибка сценария
|
## Известная ошибка сценария
|
||||||
|
|
||||||
Ошибки счетов, портфеля и подключения T-Bank остаются локальными: затронутый
|
Ошибки счетов, портфеля и подключения T-Bank остаются локальными: рядом
|
||||||
блок показывает собственное состояние и не скрывает успешно отображённые
|
с затронутыми данными доступны предусмотренные сценарием retry и navigation
|
||||||
соседние блоки. Устаревший серверный Portfolio Snapshot показывает сохранённый
|
actions. Устаревший серверный Portfolio Snapshot показывает сохранённый
|
||||||
портфель с обозначением устаревания. Он не превращается в глобальный fallback.
|
портфель с предупреждением. Он не превращается в глобальный fallback.
|
||||||
Ошибка источника не означает нулевой баланс или отсутствие операций.
|
Ошибка источника не означает нулевой баланс или отсутствие операций.
|
||||||
|
|
||||||
Предусмотренные сценарием navigation actions сохраняются: подтверждённая потеря
|
|
||||||
доступа предлагает восстановить подключение, а `404` — вернуться к списку
|
|
||||||
счетов. Это навигация и явные действия пользователя, а не повтор чтения.
|
|
||||||
|
|
||||||
## Непойманная ошибка маршрута
|
## Непойманная ошибка маршрута
|
||||||
|
|
||||||
Непойманная runtime-ошибка при отображении public или protected route
|
Непойманная runtime-ошибка при отображении public или protected route
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Development-команды ниже выполняются из workspace с che
|
|||||||
|
|
||||||
- Docker Engine с Compose plugin **не ниже 2.24.4** (`!override` в development),
|
- Docker Engine с Compose plugin **не ниже 2.24.4** (`!override` в development),
|
||||||
доступ к registry и достаточно свободного диска для non-root UID 1000.
|
доступ к registry и достаточно свободного диска для non-root UID 1000.
|
||||||
Опубликованные images собраны для Linux amd64 (см. README комплекта).
|
Production images `0.2.3` опубликованы для Linux amd64.
|
||||||
Другую архитектуру проверяют отдельно; multi-platform images не обещаны.
|
Другую архитектуру проверяют отдельно; multi-platform images не обещаны.
|
||||||
- Nexus Docker hosted repository `docker-hosted`, доступный через
|
- Nexus Docker hosted repository `docker-hosted`, доступный через
|
||||||
`nexus.personal.ksv741.ru/docker-hosted/`. Docker Bearer Token Realm включён;
|
`nexus.personal.ksv741.ru/docker-hosted/`. Docker Bearer Token Realm включён;
|
||||||
@@ -26,10 +26,7 @@ Development-команды ниже выполняются из workspace с che
|
|||||||
используется сервером для загрузки образов. Для публикации нужны
|
используется сервером для загрузки образов. Для публикации нужны
|
||||||
browse/read/add/edit на `docker-hosted`; фактически выданный набор прав
|
browse/read/add/edit на `docker-hosted`; фактически выданный набор прав
|
||||||
настраивается в Nexus. Built-in
|
настраивается в Nexus. Built-in
|
||||||
workflow token не заменяет эту настройку. Отдельной read-only учётной записи
|
workflow token не заменяет эту настройку.
|
||||||
сервера нет: `wealthledger-ci` работает и как CI writer, и как server reader,
|
|
||||||
поэтому её пароль на сервере даёт право публикации в `docker-hosted`. Это
|
|
||||||
принятое владельцем решение; разделение ролей — возможное усиление.
|
|
||||||
- На сервере Caddy уже завершает TLS и передаёт весь домен на
|
- На сервере Caddy уже завершает TLS и передаёт весь домен на
|
||||||
`127.0.0.1:8080` (или выбранный frontend port). Отдельного `/api` upstream нет.
|
`127.0.0.1:8080` (или выбранный frontend port). Отдельного `/api` upstream нет.
|
||||||
DNS, TLS, firewall и provisioning Caddy выполняются вне этого runbook.
|
DNS, TLS, firewall и provisioning Caddy выполняются вне этого runbook.
|
||||||
@@ -84,8 +81,7 @@ Workflow отказывается перезаписывать существу
|
|||||||
Выберите опубликованные version tags, выполните pull и сравните OCI revision
|
Выберите опубликованные version tags, выполните pull и сравните OCI revision
|
||||||
с release commit. Выполните smoke с disposable data/config до первого server
|
с release commit. Выполните smoke с disposable data/config до первого server
|
||||||
rollout. В `release.env` комплекта хранится пара полных image references, например
|
rollout. В `release.env` комплекта хранится пара полных image references, например
|
||||||
`nexus.personal.ksv741.ru/docker-hosted/wealthledger/frontend:1.1.0` и
|
`nexus.personal.ksv741.ru/docker-hosted/wealthledger/frontend:0.2.3`. Сохраните versions/revisions
|
||||||
`.../backend:2.1.0`. Сохраните versions/revisions
|
|
||||||
в deployment record. Release tags не должны переназначаться другим images.
|
в deployment record. Release tags не должны переназначаться другим images.
|
||||||
|
|
||||||
## Перенос существующих images из Gitea
|
## Перенос существующих images из Gitea
|
||||||
@@ -95,9 +91,7 @@ rollout. В `release.env` комплекта хранится пара полн
|
|||||||
`REGISTRY_USERNAME`/`REGISTRY_TOKEN` сохраните для отката старого workflow.
|
`REGISTRY_USERNAME`/`REGISTRY_TOKEN` сохраните для отката старого workflow.
|
||||||
Пароли вводятся интерактивно или через `--password-stdin`, не через аргументы.
|
Пароли вводятся интерактивно или через `--password-stdin`, не через аргументы.
|
||||||
|
|
||||||
Прежние images лежат в [Gitea packages](https://git.personal.ksv741.ru/WealthLedger/-/packages)
|
Скопируйте каждый опубликованный release без пересборки. Например, для `0.2.0`
|
||||||
(`git.personal.ksv741.ru/wealthledger/{frontend,backend}`); новые публикуются
|
|
||||||
только в Nexus. Скопируйте каждый опубликованный release без пересборки. Например, для `0.2.0`
|
|
||||||
с установленным Skopeo и доступом чтения Gitea/записи Nexus:
|
с установленным Skopeo и доступом чтения Gitea/записи Nexus:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -120,9 +114,7 @@ artifact повторно не публикуйте; несовпадение т
|
|||||||
После копирования сравните digests через `skopeo inspect --raw` и SHA-256,
|
После копирования сравните digests через `skopeo inspect --raw` и SHA-256,
|
||||||
выполните `docker pull` обоих images пользователем `wealthledger-ci` на сервере приложения,
|
выполните `docker pull` обоих images пользователем `wealthledger-ci` на сервере приложения,
|
||||||
проверьте OCI revision и container smoke на disposable data.
|
проверьте OCI revision и container smoke на disposable data.
|
||||||
Серверные шаги (login, pull, smoke) в репозитории не подтверждены и
|
Только после этого меняйте production image references и запускайте обычную
|
||||||
выполняются оператором. Только после них меняйте
|
|
||||||
production image references и запускайте обычную
|
|
||||||
последовательность обновления ниже. Старые Gitea packages и references сохраните:
|
последовательность обновления ниже. Старые Gitea packages и references сохраните:
|
||||||
откат registry возвращает прежние адреса тех же artifacts, не восстанавливает
|
откат registry возвращает прежние адреса тех же artifacts, не восстанавливает
|
||||||
SQLite и не меняет encryption keys. Не переносите Git release tags и не
|
SQLite и не меняет encryption keys. Не переносите Git release tags и не
|
||||||
|
|||||||
@@ -21,17 +21,6 @@ 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.
|
|
||||||
|
|
||||||
## Инвестиционные данные и синхронизация
|
## Инвестиционные данные и синхронизация
|
||||||
|
|
||||||
Затронутые GET инвестиционных ресурсов возвращают сгенерированный contract
|
Затронутые GET инвестиционных ресурсов возвращают сгенерированный contract
|
||||||
@@ -61,17 +50,6 @@ Envelope несовместим с прежними bare-array ответами:
|
|||||||
поставляются согласованной парой. Финальный artifact передаётся явно;
|
поставляются согласованной парой. Финальный artifact передаётся явно;
|
||||||
локальная генерация и CI frontend читают только собственный snapshot.
|
локальная генерация и CI frontend читают только собственный snapshot.
|
||||||
|
|
||||||
## Income analytics
|
|
||||||
|
|
||||||
`GET /api/v1/brokerage-accounts/{accountId}/income-analytics` и общий маршрут
|
|
||||||
`all` возвращают результат только выбранного периода: итоги по исходным
|
|
||||||
валютам, точные записи выплат, разбиение по инструментам и временные
|
|
||||||
интервалы. Данных сравнения с предыдущим периодом или годом ранее в ответе
|
|
||||||
нет — ни в теле, ни среди зависимостей `meta.dependencies`, роль которых
|
|
||||||
ограничена значением `selected`. Публичную машинную схему задаёт
|
|
||||||
backend-generated OpenAPI; frontend получает её обновлённый snapshot отдельно.
|
|
||||||
Точную семантику поведения описывает [доход](../domains/income/overview.md).
|
|
||||||
|
|
||||||
## Validation и identity
|
## Validation и identity
|
||||||
|
|
||||||
Backend преобразует и проверяет входные данные на общей HTTP-границе.
|
Backend преобразует и проверяет входные данные на общей HTTP-границе.
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: ["@commitlint/config-conventional"],
|
extends: ["@commitlint/config-conventional"],
|
||||||
defaultIgnores: false,
|
rules: { "type-enum": [2, "always", ["feat", "fix", "perf", "docs", "spec", "refactor", "build", "ci", "test", "style", "chore", "revert"]] },
|
||||||
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"],
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -62,8 +62,8 @@
|
|||||||
|
|
||||||
- `409 TBANK_NOT_CONNECTED`: список не запрашивается у T-Bank, экран ведёт в настройки.
|
- `409 TBANK_NOT_CONNECTED`: список не запрашивается у T-Bank, экран ведёт в настройки.
|
||||||
- `400 INVALID_TBANK_TOKEN`: сохранённый токен не удаляется, экран ведёт в настройки для замены или удаления.
|
- `400 INVALID_TBANK_TOKEN`: сохранённый токен не удаляется, экран ведёт в настройки для замены или удаления.
|
||||||
- `503 TBANK_UNAVAILABLE`: экран показывает спокойное состояние недоступности; чтение возобновляется автоматически.
|
- `503 TBANK_UNAVAILABLE`: экран предлагает повторить загрузку или открыть настройки.
|
||||||
- Неизвестная ошибка: то же состояние недоступности без действия повтора.
|
- Неизвестная ошибка: экран предлагает только повторить загрузку.
|
||||||
- Успешный пустой ответ: штатное состояние отсутствия инвестиционных счетов.
|
- Успешный пустой ответ: штатное состояние отсутствия инвестиционных счетов.
|
||||||
|
|
||||||
Карточка ведёт на `/accounts/:accountId` по всей области и доступна с клавиатуры. Карточки расположены в одну колонку при любой ширине. Карточка показывает название, локализованный тип, крупный валютный итог и вторую валюту при наличии, число остальных валют, дату открытия без времени и видимое действие открытия. Отдельные цветные блоки «Акции» и «Облигации» показывают количество наименований бумаг. Недоступная или пустая сводка отображается локально; отсутствие сумм не скрывает известные количества бумаг, а недоступная сводка не подменяет их нулями. Наведение и видимый клавиатурный фокус подчёркивают переход; настройка уменьшения движения отключает анимацию.
|
Карточка ведёт на `/accounts/:accountId` по всей области и доступна с клавиатуры. Карточки расположены в одну колонку при любой ширине. Карточка показывает название, локализованный тип, крупный валютный итог и вторую валюту при наличии, число остальных валют, дату открытия без времени и видимое действие открытия. Отдельные цветные блоки «Акции» и «Облигации» показывают количество наименований бумаг. Недоступная или пустая сводка отображается локально; отсутствие сумм не скрывает известные количества бумаг, а недоступная сводка не подменяет их нулями. Наведение и видимый клавиатурный фокус подчёркивают переход; настройка уменьшения движения отключает анимацию.
|
||||||
@@ -71,10 +71,9 @@
|
|||||||
## Свежесть и границы
|
## Свежесть и границы
|
||||||
|
|
||||||
Обычное открытие использует query owner и локальный server snapshot.
|
Обычное открытие использует query owner и локальный server snapshot.
|
||||||
«Обновить» перечитывает сохранённые membership и сводки доступных счетов;
|
«Обновить» запрашивает membership и сводки доступных счетов; активная работа
|
||||||
активная работа наблюдается без нового импорта. Истечение TTL само не
|
наблюдается без нового импорта. Истечение TTL само не запускает запрос.
|
||||||
запускает запрос: обновлением личных данных владеет часовой обход.
|
Membership имеет пятиминутную свежесть, portfolio — минутную. Время списка
|
||||||
Membership и portfolio source имеют часовую свежесть. Время списка
|
|
||||||
не подменяет время каждой сводки. Список не заменяет полный
|
не подменяет время каждой сводки. Список не заменяет полный
|
||||||
[портфель](../portfolio/overview.md), [журнал](../operations/overview.md)
|
[портфель](../portfolio/overview.md), [журнал](../operations/overview.md)
|
||||||
или историю закрытых счетов. Для общего результата доступен
|
или историю закрытых счетов. Для общего результата доступен
|
||||||
|
|||||||
@@ -11,20 +11,14 @@
|
|||||||
|
|
||||||
Пользователь регистрируется или входит по email и паролю. Регистрация сразу
|
Пользователь регистрируется или входит по email и паролю. Регистрация сразу
|
||||||
создаёт первую сессию. Внешние пробелы email удаляются, буквы приводятся
|
создаёт первую сессию. Внешние пробелы email удаляются, буквы приводятся
|
||||||
к нижнему регистру.
|
к нижнему регистру. Backend требует пароль не короче 12 символов и не длиннее
|
||||||
|
72 UTF-8 байтов.
|
||||||
|
|
||||||
Пароль при регистрации — от 8 до 72 печатных ASCII-символов: латинские
|
**Известное расхождение:** сохранённое требование регистрации и проверка
|
||||||
буквы, цифры, спецсимволы и пробел. Кириллица, emoji, другие не-ASCII и
|
в форме frontend считают нижнюю границу в UTF-8 байтах, а backend — в символах.
|
||||||
управляющие символы отклоняются. Пароль не обрезается и не нормализуется, а
|
Не-ASCII пароль может пройти форму и получить отказ API. Это не принятое
|
||||||
обязательных классов символов нет. Верхняя граница вытекает из bcrypt, который
|
изменение password policy; требуется отдельное согласованное решение
|
||||||
учитывает только первые 72 байта: для ASCII символ равен байту, поэтому
|
о проверке пароля и подтверждение полного HTTP-потока.
|
||||||
длинный пароль не обрезается молча. Frontend и backend проверяют одну и ту же
|
|
||||||
политику.
|
|
||||||
|
|
||||||
При входе проверяется только то, что пароль непустой и не длиннее 72 UTF-8
|
|
||||||
байтов. Минимум и набор символов не применяются, чтобы пользователь,
|
|
||||||
зарегистрированный по прежним правилам (в том числе с не-ASCII паролем), мог
|
|
||||||
войти. Невалидный пароль получает `400` с кодом `VALIDATION_ERROR`.
|
|
||||||
|
|
||||||
Access token действует 15 минут и хранится только в памяти браузера.
|
Access token действует 15 минут и хранится только в памяти браузера.
|
||||||
Refresh token имеет серверный срок 7 дней, заменяется при восстановлении
|
Refresh token имеет серверный срок 7 дней, заменяется при восстановлении
|
||||||
|
|||||||
+28
-13
@@ -4,7 +4,7 @@
|
|||||||
купонами и дивидендами за выбранный период». Пользователь открывает
|
купонами и дивидендами за выбранный период». Пользователь открывает
|
||||||
`/accounts/:accountId/income` из обзора счёта или
|
`/accounts/:accountId/income` из обзора счёта или
|
||||||
[общий доход](../portfolio/all-accounts.md) по доступным счетам.
|
[общий доход](../portfolio/all-accounts.md) по доступным счетам.
|
||||||
Экран показывает итоги по валютам и отдельную карточку каждой
|
Экран показывает итоги по валютам, сравнение и отдельную карточку каждой
|
||||||
включённой выплаты. Источником служат [исполненные операции](../operations/overview.md),
|
включённой выплаты. Источником служат [исполненные операции](../operations/overview.md),
|
||||||
а не изменение цены портфеля и не календарь будущих выплат.
|
а не изменение цены портфеля и не календарь будущих выплат.
|
||||||
|
|
||||||
@@ -38,12 +38,11 @@
|
|||||||
|
|
||||||
При первой загрузке или новом периоде без сохранённых данных показан
|
При первой загрузке или новом периоде без сохранённых данных показан
|
||||||
каркас страницы. Пустой результат объясняет отсутствие исполненных купонов и
|
каркас страницы. Пустой результат объясняет отсутствие исполненных купонов и
|
||||||
дивидендов, сохраняя фильтры и налоговое пояснение. Ошибка запроса
|
дивидендов, сохраняя фильтры, налоговое пояснение и сравнения. Ошибка запроса
|
||||||
или нарушение принадлежности выплат даёт локальное состояние недоступности
|
или нарушение принадлежности выплат даёт локальное состояние с действием «Повторить».
|
||||||
без действия повтора; чтение восстанавливается автоматически.
|
|
||||||
При фоновом обновлении того же периода сохранённый ответ и черновик
|
При фоновом обновлении того же периода сохранённый ответ и черновик
|
||||||
остаются видимыми без индикации обновления и технического предупреждения.
|
остаются видимыми: загрузку обозначает индикатор, неуспешное обновление —
|
||||||
Неполнота применённого периода обозначается состоянием самого результата.
|
предупреждение с повторной попыткой.
|
||||||
|
|
||||||
На узком экране поля и действия идут вертикально; все карточки выплат
|
На узком экране поля и действия идут вертикально; все карточки выплат
|
||||||
остаются в общем потоке страницы без раскрытия или внутренних областей прокрутки.
|
остаются в общем потоке страницы без раскрытия или внутренних областей прокрутки.
|
||||||
@@ -52,15 +51,32 @@
|
|||||||
|
|
||||||
- Backend проверяет доступ локально и читает сохранённые операции. Фоновая загрузка должна завершить все страницы; ошибка страницы или повреждённая цепочка курсоров не подтверждают полноту.
|
- Backend проверяет доступ локально и читает сохранённые операции. Фоновая загрузка должна завершить все страницы; ошибка страницы или повреждённая цепочка курсоров не подтверждают полноту.
|
||||||
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в исходной валюте; отрицательные корректировки сохраняют знак. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
|
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в исходной валюте; отрицательные корректировки сохраняют знак. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
|
||||||
- Итоги, временные интервалы и разбиение по инструментам не смешивают валюты и не создают общий конвертированный итог. Система не загружает другие периоды ради сравнения полученного дохода с выбранным.
|
- Итоги, сравнения, временные интервалы и разбиение по инструментам не смешивают валюты и не создают общий конвертированный итог. Страница показывает сравнения с предыдущим периодом и годом ранее, когда календарная дата и история счёта позволяют. Неполное сравнение имеет отдельное сообщение, без нулевой базы.
|
||||||
- Временные интервалы по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые интервалы. Страница дохода не строит из них график или текстовую динамику; ответ API не меняется.
|
- Временные интервалы по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые интервалы. Страница дохода не строит из них график или текстовую динамику; ответ API не меняется.
|
||||||
- Раздел «Выплаты» показывает единый список карточек выплат в исходном порядке `entries`: одна карточка на каждую выплату. Внешних групп по инструментам или валютам, итогов и количества выплат инструмента нет. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой карточке; валюты разделены в итогах. Дополнительный запрос за составом не нужен.
|
- Раздел «Выплаты» показывает единый список карточек выплат в исходном порядке `entries`: одна карточка на каждую выплату. Внешних групп по инструментам или валютам, итогов и количества выплат инструмента нет. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой карточке; валюты по-прежнему разделены в итогах и сравнениях. Дополнительный запрос за составом не нужен.
|
||||||
|
|
||||||
|
Сравнение с непосредственно предыдущим периодом использует предыдущий полный
|
||||||
|
месяц для полного выбранного месяца, иначе — непосредственно предшествующий
|
||||||
|
интервал той же включительной длительности. Оно не подменяет сравнение годом
|
||||||
|
ранее. Незагруженное сравнение и ошибка его источника отличаются от
|
||||||
|
недоступности годового сравнения по календарю или дате открытия счёта.
|
||||||
|
|
||||||
|
Каждый раздел сравнения показывает цветные панели без общей белой подложки и
|
||||||
|
внутренних отступов у внешнего блока. Точные периоды показаны в заголовках двух панелей с русским форматом диапазона
|
||||||
|
и UTC для календарных дат.
|
||||||
|
Отдельного заголовка с датами и валютного бейджа нет; валюта остаётся у каждой суммы.
|
||||||
|
Панель «Разница» сохраняет серверную абсолютную разницу и дополняет итог, купоны
|
||||||
|
и дивиденды процентом: абсолютная разница / сумма годом ранее × 100.
|
||||||
|
Это округлённый показатель для отображения, а не пересчёт Money или инвестиционная
|
||||||
|
доходность. Форматирование сохраняет знак и не более одного десятичного разряда.
|
||||||
|
При нулевой или отрицательной базе либо непредставимом числовом отношении
|
||||||
|
процентный бейдж не отображается; абсолютная разница остаётся видимой.
|
||||||
|
|
||||||
## Полнота и принадлежность выплат
|
## Полнота и принадлежность выплат
|
||||||
|
|
||||||
Доходы читают сохранённые операции и coverage в согласованной транзакции.
|
Доходы читают сохранённые операции и coverage в согласованной транзакции.
|
||||||
Только выбранный период определяет готовность результата. Неполный период
|
Selected, previous и yearAgo имеют независимую готовность. Неполный selected
|
||||||
не получает окончательных итогов.
|
не получает окончательных итогов; неполное сравнение не создаёт нулевую базу.
|
||||||
Подтверждённый пустой период отличается от ещё не загруженного. При смене
|
Подтверждённый пустой период отличается от ещё не загруженного. При смене
|
||||||
периода прежний snapshot не показывается под новым названием.
|
периода прежний snapshot не показывается под новым названием.
|
||||||
|
|
||||||
@@ -87,12 +103,11 @@ Backend обеспечивает принадлежность выплат, ва
|
|||||||
|
|
||||||
## Будущие события и ограничения
|
## Будущие события и ограничения
|
||||||
|
|
||||||
На странице дохода нет блоков «Динамика» и «Ближайший прогноз», блоков
|
На странице дохода нет блоков «Динамика» и «Ближайший прогноз». Она не запрашивает
|
||||||
сравнения периодов и сообщений об их недоступности. Она не запрашивает
|
|
||||||
`/events` и не зависит от его доступности. Самостоятельная страница
|
`/events` и не зависит от его доступности. Самостоятельная страница
|
||||||
[«Будущие события»](upcoming-events.md) по-прежнему доступна из обзора
|
[«Будущие события»](upcoming-events.md) по-прежнему доступна из обзора
|
||||||
выбранного счёта и сохраняет прежнее поведение. Будущие выплаты
|
выбранного счёта и сохраняет прежнее поведение. Будущие выплаты
|
||||||
не включаются в итоги полученного дохода.
|
не включаются в итоги полученного дохода или сравнения.
|
||||||
|
|
||||||
Аналитика читает сохранённую историю операций и не рассчитывает налоги, инвестиционную эффективность, доходность, валютную конвертацию или общий мультивалютный итог.
|
Аналитика читает сохранённую историю операций и не рассчитывает налоги, инвестиционную эффективность, доходность, валютную конвертацию или общий мультивалютный итог.
|
||||||
|
|
||||||
|
|||||||
@@ -39,23 +39,13 @@
|
|||||||
|
|
||||||
## Период и список
|
## Период и список
|
||||||
|
|
||||||
Без фильтра страница применяет период по умолчанию из семи календарных
|
Без фильтра период начинается сегодня в UTC и заканчивается через 30 дней
|
||||||
дат включительно: сегодняшней и шести следующих календарных дней. API при
|
после начала, обе даты включены. `from` и `to` принимают только строгие даты
|
||||||
отсутствии параметров использует своё окно (от текущей даты UTC до `from + 30`
|
`YYYY-MM-DD`; без `from` используется текущая дата UTC, без `to` — `from + 30`
|
||||||
календарных дней), обе даты включены; `from` и `to` принимают только строгие
|
календарных дней. Поля «С» и «По» сохраняют выбранные календарные даты в URL,
|
||||||
даты `YYYY-MM-DD`. Календарь фильтра разрешает выбор сегодняшней и будущих дат
|
а «Сбросить» возвращает период по умолчанию.
|
||||||
и не позволяет выбрать даты раньше сегодняшней. Прямая ссылка с валидным
|
|
||||||
прошедшим периодом сохраняет указанные даты без замены; некорректный формат,
|
|
||||||
несуществующая календарная дата или обратный диапазон нормализуются к периоду
|
|
||||||
по умолчанию с удалением параметров из URL. Поля «С» и «По» сохраняют
|
|
||||||
выбранные календарные даты в URL, а «Сбросить» возвращает период по умолчанию.
|
|
||||||
|
|
||||||
События упорядочены по календарной дате. Купоны и дивиденды показываются
|
События упорядочены по календарной дате. У каждой строки видны тип,
|
||||||
единым предметным представлением выплаты с явной пометкой прогноза — тем же,
|
|
||||||
что у исполненных выплат в доходе и журнале; неизвестная сумма остаётся
|
|
||||||
«сумма неизвестна» и не превращается в ноль или полученные деньги.
|
|
||||||
Дата дивиденда обозначена как дата реестра. Offer и погашение сохраняют своё
|
|
||||||
значение без суммы выплаты. У каждой строки видны тип,
|
|
||||||
инструмент, дата и доступная сумма в исходной валюте. Список не имеет
|
инструмент, дата и доступная сумма в исходной валюте. Список не имеет
|
||||||
пагинации и не конвертирует валюты. Пустой результат означает отсутствие
|
пагинации и не конвертирует валюты. Пустой результат означает отсутствие
|
||||||
известных поддерживаемых событий в выбранном окне, а не доказательство
|
известных поддерживаемых событий в выбранном окне, а не доказательство
|
||||||
|
|||||||
@@ -89,11 +89,7 @@ HTML-источник, общий кэш и поведение при измен
|
|||||||
|
|
||||||
Календарь охватывает пять прошлых лет и следующий год. Будущие купоны
|
Календарь охватывает пять прошлых лет и следующий год. Будущие купоны
|
||||||
сортируются по дате выплаты, прошедшие и недатированные доступны отдельно.
|
сортируются по дате выплаты, прошедшие и недатированные доступны отдельно.
|
||||||
Будущие и прошедшие события купонного графика показываются единым предметным
|
Показаны сумма на облигацию, номер, тип, длительность периода и дата реестра,
|
||||||
представлением выплаты с пометкой события по графику — тем же, что у
|
|
||||||
исполненных выплат и прогноза; исполнение подтверждает только личная история.
|
|
||||||
Показаны сумма на облигацию, отдельная личная оценка, номер, тип, длительность
|
|
||||||
периода и дата реестра,
|
|
||||||
если они известны. Неопределённый будущий купон не заменяется нулём.
|
если они известны. Неопределённый будущий купон не заменяется нулём.
|
||||||
|
|
||||||
Личная оценка доступна только при положительных позициях, известной сумме,
|
Личная оценка доступна только при положительных позициях, известной сумме,
|
||||||
@@ -121,8 +117,8 @@ HTML-источник, общий кэш и поведение при измен
|
|||||||
portfolio; они не попадают в общие источники.
|
portfolio; они не попадают в общие источники.
|
||||||
|
|
||||||
BondBy переиспользуется зависимостями выпуска. Discovery принадлежит query,
|
BondBy переиспользуется зависимостями выпуска. Discovery принадлежит query,
|
||||||
свежесть — конкретному source/range. Missing/stale зависимости ставятся
|
свежесть — конкретному source/range. Missing/stale зависимости запрашиваются
|
||||||
в фоновую очередь через прежний limiter; обычный HTTP-ответ не ждёт брокера.
|
в фоне через прежний limiter; обычный HTTP-ответ не ждёт брокера.
|
||||||
Покрытые завершённые свечи не перечитываются после restart. Открытый хвост
|
Покрытые завершённые свечи не перечитываются после restart. Открытый хвост
|
||||||
остаётся изменяемым; ручной refresh охватывает показанный период.
|
остаётся изменяемым; ручной refresh охватывает показанный период.
|
||||||
|
|
||||||
@@ -131,8 +127,7 @@ BondBy переиспользуется зависимостями выпуск
|
|||||||
выплат. Наблюдение статуса не запускает повторный импорт. Политика источников
|
выплат. Наблюдение статуса не запускает повторный импорт. Политика источников
|
||||||
и границы — в [модели свежести](../../architecture/cross-cutting/data-freshness.md).
|
и границы — в [модели свежести](../../architecture/cross-cutting/data-freshness.md).
|
||||||
|
|
||||||
Разделы загружаются независимо, показывают каркас загрузки и локальное
|
Разделы загружаются независимо, показывают каркас загрузки и локальную повторную попытку.
|
||||||
спокойное состояние недоступности без действия повтора.
|
|
||||||
Ошибка фонового обновления сохраняет последние данные. Смена подключения
|
Ошибка фонового обновления сохраняет последние данные. Смена подключения
|
||||||
сбрасывает поддерево клиентских запросов облигаций вместе с остальными финансовыми запросами;
|
сбрасывает поддерево клиентских запросов облигаций вместе с остальными финансовыми запросами;
|
||||||
выход очищает кэш сессии. Общие график, позиция и личные события
|
выход очищает кэш сессии. Общие график, позиция и личные события
|
||||||
@@ -151,6 +146,6 @@ BondBy переиспользуется зависимостями выпуск
|
|||||||
|
|
||||||
## Online reference
|
## Online reference
|
||||||
|
|
||||||
Страница облигации, поиск и переход по тикеру обращаются к онлайн-справочнику
|
Bond detail, search, and ticker lookup are read from the upstream integration
|
||||||
брокера; сохранённые quotes, свечи, события, ratings и метки портфеля
|
on each request. Saved quotes, candles, events, ratings, and portfolio labels
|
||||||
сохраняют собственные границы свежести и ошибок.
|
retain their own freshness and failure boundaries.
|
||||||
|
|||||||
@@ -28,30 +28,24 @@
|
|||||||
на frontend. Общее для акций и облигаций восстановление справочных данных
|
на frontend. Общее для акций и облигаций восстановление справочных данных
|
||||||
принадлежит [загрузке портфеля на backend](../portfolio/flows/portfolio-loading.md).
|
принадлежит [загрузке портфеля на backend](../portfolio/flows/portfolio-loading.md).
|
||||||
|
|
||||||
Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: скринер
|
Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: поиск
|
||||||
запускается кнопкой «Найти» с необязательным названием или тикером, сектором,
|
по названию или тикеру через каталог Т-Банка, начиная с двух символов.
|
||||||
типом акции, валютой расчётов, площадкой, страной риска и максимальным размером
|
Результаты разных выпусков, включая обыкновенные и привилегированные акции,
|
||||||
лота. Он использует полный полученный каталог и показывает только акции, для
|
имеют отдельные UID. Карточка результата показывает логотип, последнюю цену
|
||||||
которых каталог подтверждает доступность покупки и торговли через API. Это не
|
с её временем, тип бумаги, площадку, код режима, ISIN и доступность торгов через
|
||||||
гарантирует, что конкретная заявка пользователя будет исполнена прямо сейчас.
|
API. Поиск показывает одну карточку на нормализованный ISIN. До ограничения
|
||||||
|
в 30 результатов выбирается представитель выпуска: доступность через API,
|
||||||
Скринер показывает одну карточку на выпуск с нормализованным ISIN, а выпуск
|
точное совпадение тикера, затем режим TQBR; равные варианты упорядочены по UID.
|
||||||
без ISIN остаётся отдельной карточкой точного UID. Обыкновенные и
|
Записи без ISIN сохраняются отдельно по UID. Обыкновенные и привилегированные
|
||||||
привилегированные акции с разными ISIN не объединяются. После отбора карточки
|
акции с разными ISIN не объединяются. Цена и ссылка принадлежат выбранному
|
||||||
упорядочены по тикеру и UID, разделены на страницы по 30 и показывают единое
|
UID; данные разных режимов не смешиваются. Прямые ссылки из портфеля сохраняют
|
||||||
время получения списка. Изменение условий не заменяет текущий список до
|
|
||||||
следующего нажатия «Найти». Повторный поиск получает новый каталог; страницы
|
|
||||||
одного результата не пересчитываются. Подтверждённый пустой результат отличается
|
|
||||||
от ошибки источника: она сообщается рядом с полем поиска, а повторить запрос
|
|
||||||
пользователь может обычным «Найти» — отдельного действия повтора чтения нет.
|
|
||||||
|
|
||||||
Ссылка карточки принадлежит выбранному UID; данные разных режимов не смешиваются.
|
|
||||||
Прямые ссылки из портфеля сохраняют
|
|
||||||
исходный UID, даже если поиск выбрал другой режим этого выпуска; такая страница
|
исходный UID, даже если поиск выбрал другой режим этого выпуска; такая страница
|
||||||
сохраняет UUID в адресе. Если один точный тикер относится к разным выпускам,
|
сохраняет UUID в адресе. Если один точный тикер относится к разным выпускам,
|
||||||
сервер возвращает `409 STOCK_TICKER_AMBIGUOUS`.
|
сервер возвращает `409 STOCK_TICKER_AMBIGUOUS`, а страница предлагает поиск.
|
||||||
|
Поиск тикера нечувствителен к регистру, но использует точное совпадение:
|
||||||
|
SBER не заменяется на SBERP. Однобуквенные тикеры также поддерживаются.
|
||||||
Прямая ссылка не требует предварительного открытия портфеля. Хлебные крошки
|
Прямая ссылка не требует предварительного открытия портфеля. Хлебные крошки
|
||||||
«Акции → название» возвращают к скринеру.
|
«Акции → название» возвращают к поиску.
|
||||||
|
|
||||||
## Содержание и состояния
|
## Содержание и состояния
|
||||||
|
|
||||||
@@ -64,9 +58,8 @@
|
|||||||
рыночные данные и личная история остаются доступны.
|
рыночные данные и личная история остаются доступны.
|
||||||
|
|
||||||
Каждый раздел загружается независимо. Первичная загрузка показывает каркас
|
Каждый раздел загружается независимо. Первичная загрузка показывает каркас
|
||||||
раздела, затянувшаяся недоступность — локальное спокойное состояние без
|
раздела, ошибка — локальную повторную попытку. При ошибке фонового обновления
|
||||||
повторной попытки. При ошибке фонового обновления сохраняются предыдущие
|
сохраняются предыдущие данные и предупреждение. Цена содержит собственное время
|
||||||
данные без технического предупреждения. Цена содержит собственное время
|
|
||||||
UTC, которое может быть старше времени получения ответа. Статус торгов не
|
UTC, которое может быть старше времени получения ответа. Статус торгов не
|
||||||
выводится из свежести цены. Отсутствующее значение не заменяется нулём.
|
выводится из свежести цены. Отсутствующее значение не заменяется нулём.
|
||||||
|
|
||||||
@@ -126,11 +119,7 @@ UID включён в ключ кэша и подпись общего курс
|
|||||||
|
|
||||||
## Дивиденды и финансовые показатели
|
## Дивиденды и финансовые показатели
|
||||||
|
|
||||||
События компании отделены от личных зачислений. Будущие и прошедшие события
|
События компании отделены от личных зачислений. Известные будущие выплаты
|
||||||
дивидендного графика показываются единым предметным представлением выплаты
|
|
||||||
с пометкой «событие по графику» — тем же, что у исполненных выплат и прогноза;
|
|
||||||
сумма на акцию, отдельная личная оценка и дата реестра сохраняют свои подписи
|
|
||||||
и не выдаются за личное зачисление. Известные будущие выплаты
|
|
||||||
определяются по `paymentDate`, при её отсутствии — по `recordDate`; прошедшие
|
определяются по `paymentDate`, при её отсутствии — по `recordDate`; прошедшие
|
||||||
и недатированные события помещены в отдельную историю компании. Отменённые
|
и недатированные события помещены в отдельную историю компании. Отменённые
|
||||||
события исключаются. Личная оценка умножает сумму на акцию на текущее положительное
|
события исключаются. Личная оценка умножает сумму на акцию на текущее положительное
|
||||||
@@ -155,22 +144,19 @@ TTM означает последние 12 месяцев, MRQ — послед
|
|||||||
## Получение данных и ограничения
|
## Получение данных и ограничения
|
||||||
|
|
||||||
Общие metadata, discovery, company, quotes, свечи и календари сохраняются
|
Общие metadata, discovery, company, quotes, свечи и календари сохраняются
|
||||||
в SQLite. Скринер получает каталог online и показывает время его получения;
|
в SQLite. Поиск хранит подтверждённый набор UID для конкретного query;
|
||||||
временная недоступность каталога не подтверждает отсутствие подходящих акций.
|
успешный SBER не подтверждает пустой GAZP. Отсутствующее enrichment не
|
||||||
Отсутствующее enrichment не скрывает найденную бумагу. Сохранённые общие
|
скрывает найденную бумагу. Сохранённые общие источники переиспользуются
|
||||||
источники переиспользуются между пользователями, но личные позиции и выплаты
|
между пользователями, но личные позиции и выплаты всегда проверяют доступ.
|
||||||
всегда проверяют доступ.
|
|
||||||
|
|
||||||
Обычное чтение не ждёт RPC; missing/stale зависимости ставятся в фоновую
|
Обычное чтение не ждёт RPC; missing/stale зависимости запрашиваются в фоне
|
||||||
очередь через существующий T-Bank limiter. Часовая свежесть применяется
|
через существующий T-Bank limiter. Минутная свежесть применяется к quotes
|
||||||
к quotes и открытому хвосту свечей; metadata/company/календари, будучи
|
и открытому хвосту свечей, суточная — к metadata/company/календарям.
|
||||||
сохранёнными, не перечитываются обычным чтением.
|
|
||||||
Закрытые полные свечные интервалы, включая пустые, сохраняются после restart.
|
Закрытые полные свечные интервалы, включая пустые, сохраняются после restart.
|
||||||
Новый день не делает прежнюю незавершённую свечу полной.
|
Новый день не делает прежнюю незавершённую свечу полной.
|
||||||
|
|
||||||
Отдельного действия «Обновить» на странице нет: чтение текущего инструмента,
|
«Обновить» передаёт текущий инструмент, выбранный график и personal-history
|
||||||
выбранного графика и personal-history scope выполняется автоматически.
|
scope. Частичные строки видны с предупреждением; неполные личные оценки
|
||||||
Частичные строки видны с обозначением неполноты; неполные личные оценки
|
|
||||||
не становятся нулями. Статус и `sync=observe` не создают новый импорт.
|
не становятся нулями. Статус и `sync=observe` не создают новый импорт.
|
||||||
Смена подключения и известный access loss очищают личное представление;
|
Смена подключения и известный access loss очищают личное представление;
|
||||||
поздние ответы не возвращают прежние данные. Детали —
|
поздние ответы не возвращают прежние данные. Детали —
|
||||||
@@ -201,6 +187,7 @@ TTM означает последние 12 месяцев, MRQ — послед
|
|||||||
|
|
||||||
## Online reference
|
## Online reference
|
||||||
|
|
||||||
Страница акции, поиск и переход по тикеру обращаются к онлайн-справочнику
|
Stock detail, company data, search, and ticker lookup are read from the
|
||||||
брокера; сохранённые позиции, quotes, свечи и события остаются независимыми
|
upstream integration on each request. Saved positions, quotes, candles, and
|
||||||
локальными ресурсами и не подменяются ошибкой справочника.
|
events remain independent local resources and are not replaced by a reference
|
||||||
|
read failure.
|
||||||
|
|||||||
@@ -84,10 +84,8 @@ Coverage/status без изменения rowset cursor не ломают. Пе
|
|||||||
|
|
||||||
Полный журнал и превью используют одинаковую компактную строку: логотип
|
Полный журнал и превью используют одинаковую компактную строку: логотип
|
||||||
или буквенная заглушка, описание, дата, инструмент и денежное движение.
|
или буквенная заглушка, описание, дата, инструмент и денежное движение.
|
||||||
Исполненные купоны и дивиденды показываются единым предметным представлением
|
Для купона и дивиденда денежная метка называет точное событие; для прочих
|
||||||
выплаты — тем же, что на странице дохода, в прогнозе и графиках инструментов;
|
операций — категорию. Она показывается один раз, без повтора рядом с датой.
|
||||||
денежная метка называет точное исполненное событие. Для прочих
|
|
||||||
операций метка называет категорию. Она показывается один раз, без повтора рядом с датой.
|
|
||||||
Знак и цвет обозначают направление денег; отсутствие движения нейтрально.
|
Знак и цвет обозначают направление денег; отсутствие движения нейтрально.
|
||||||
Если описание отсутствует, показывается локализованный тип операции.
|
Если описание отсутствует, показывается локализованный тип операции.
|
||||||
|
|
||||||
|
|||||||
@@ -53,10 +53,13 @@ Backend публикует статические маршруты под `/api/
|
|||||||
- Журнал объединяет операции по убыванию времени, при равном времени использует
|
- Журнал объединяет операции по убыванию времени, при равном времени использует
|
||||||
порядок идентификаторов счетов и операций. ID
|
порядок идентификаторов счетов и операций. ID
|
||||||
операций разных счетов не считаются дублями. Переводы не схлопываются.
|
операций разных счетов не считаются дублями. Переводы не схлопываются.
|
||||||
- Доходы собираются из всех страниц операций каждого счёта за выбранный период.
|
- Доходы рассчитываются из согласованной локальной выборки операций за общие периоды.
|
||||||
Итоги, временные интервалы и принадлежность выплат рассчитывает
|
Итоги, сравнения, временные интервалы и принадлежность выплат рассчитывает
|
||||||
сервис дохода. Данные сравнения периодов не загружаются и не возвращаются;
|
сервис дохода.
|
||||||
состав счетов влияет только на фактические выплаты выбранного периода.
|
Для сравнения с годом ранее используется текущий состав счетов; новый счёт
|
||||||
|
добавляет только реально полученные выплаты. При известных датах открытия всех счетов
|
||||||
|
доступность сравнения определяется самым ранним открытием в этом составе.
|
||||||
|
Закрытые счета в историческое сравнение не добавляются.
|
||||||
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
|
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
|
||||||
Прогноз не включается в реализованные доходы.
|
Прогноз не включается в реализованные доходы.
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
| Cash Balance | Суммы из `GetPositions.money`, объединённые по валюте | Заблокированные деньги не прибавляются; торгуемый инструмент `CURRENCY` остаётся позицией |
|
| Cash Balance | Суммы из `GetPositions.money`, объединённые по валюте | Заблокированные деньги не прибавляются; торгуемый инструмент `CURRENCY` остаётся позицией |
|
||||||
| `totalsByCurrency` | Стоимости позиций + доступные деньги той же валюты | Не включает невычислимую стоимость; не обещает полную оценку портфеля |
|
| `totalsByCurrency` | Стоимости позиций + доступные деньги той же валюты | Не включает невычислимую стоимость; не обещает полную оценку портфеля |
|
||||||
| `lastSuccessfulAt` | Время формирования успешного снимка, UTC | Не является временем каждой котировки; запасной снимок сохраняет исходное время |
|
| `lastSuccessfulAt` | Время формирования успешного снимка, UTC | Не является временем каждой котировки; запасной снимок сохраняет исходное время |
|
||||||
| `isStale` | Истёк часовой срок свежести сохранённого portfolio source | Не описывает состояние клиентского кэша или ошибку фонового запроса |
|
| `isStale` | Истёк минутный срок свежести сохранённого portfolio source | Не описывает состояние клиентского кэша или ошибку фонового запроса |
|
||||||
|
|
||||||
Ненулевые денежные остатки одной валюты суммируются. Позиции одинаковых
|
Ненулевые денежные остатки одной валюты суммируются. Позиции одинаковых
|
||||||
инструментов в ответе отдельного счёта не объединяются; визуальная группировка
|
инструментов в ответе отдельного счёта не объединяются; визуальная группировка
|
||||||
|
|||||||
@@ -12,12 +12,11 @@
|
|||||||
величины. Убедитесь, что сравниваемые значения относятся к одному составу
|
величины. Убедитесь, что сравниваемые значения относятся к одному составу
|
||||||
счетов и инструменту. Название или тикер сами по себе не доказывают
|
счетов и инструменту. Название или тикер сами по себе не доказывают
|
||||||
совпадение выпуска; используйте доступные UID, FIGI и ISIN.
|
совпадение выпуска; используйте доступные UID, FIGI и ISIN.
|
||||||
2. **Сопоставьте время.** Проверьте `lastSuccessfulAt`, `isStale` и показанный
|
2. **Сопоставьте время.** Проверьте `lastSuccessfulAt`, `isStale` и наличие
|
||||||
исход последней часовой попытки. Серверный снимок не обещает время
|
предупреждения о клиентском обновлении. Серверный снимок не обещает время
|
||||||
каждой котировки, а общий портфель может соединять разные моменты.
|
каждой котировки, а общий портфель может соединять разные моменты.
|
||||||
Действия «Повторить» на экране нет: временный сбой чтения восстанавливается
|
Если запрос завершился ошибкой, доступное действие «Повторить» должно
|
||||||
автоматически, поэтому расхождение проверяйте по показанному состоянию
|
обновить результат или оставить объяснимую ошибку. Перезагрузка backend
|
||||||
источника, а не по результату ручного обновления. Перезагрузка backend
|
|
||||||
сохраняет последний полный снимок в SQLite, но не создаёт историю стоимости.
|
сохраняет последний полный снимок в SQLite, но не создаёт историю стоимости.
|
||||||
3. **Проверьте состав суммы.** Для одной валюты итог складывается из
|
3. **Проверьте состав суммы.** Для одной валюты итог складывается из
|
||||||
вычислимых стоимостей позиций и доступных денег. Не добавляйте деньги
|
вычислимых стоимостей позиций и доступных денег. Не добавляйте деньги
|
||||||
|
|||||||
@@ -79,23 +79,18 @@ Backend получает данные через серверную
|
|||||||
не содержат данных и не получают фокус. При обычном фоновом обновлении
|
не содержат данных и не получают фокус. При обычном фоновом обновлении
|
||||||
сохраняются предыдущие суммы и время успешного получения в UTC.
|
сохраняются предыдущие суммы и время успешного получения в UTC.
|
||||||
|
|
||||||
Серверный `isStale` обозначает возраст снимка старше часа: обновлением
|
Серверный `isStale` обозначает истечение минутной свежести снимка.
|
||||||
владеет часовой обход, а не запрос экрана. Он показывается рядом с суммами
|
Клиентское предупреждение означает неудачную попытку обновить уже показанный
|
||||||
вместе с временем последнего успешного результата и исходом последней часовой
|
ответ. Эти состояния независимы и могут появиться одновременно.
|
||||||
попытки. Неудачная попытка клиента обновить уже показанный ответ о себе не
|
Успешный повторный запрос обновляет суммы и время, снимает клиентскую ошибку;
|
||||||
сообщает: эти состояния независимы, но пользователю видимо только состояние
|
серверное предупреждение определяется новым `isStale`.
|
||||||
источника. Успешное автоматическое перечитывание обновляет суммы и время;
|
|
||||||
обозначение устаревания определяется новым `isStale`.
|
|
||||||
Правила времени и ошибок приведены в [потоке загрузки](flows/portfolio-loading.md).
|
Правила времени и ошибок приведены в [потоке загрузки](flows/portfolio-loading.md).
|
||||||
|
|
||||||
Отдельного чтения истории стоимости нет, но каждый полный снимок
|
В текущем решении нет долговременной истории снимков, графиков стоимости
|
||||||
сохраняет точку оценки по счёту и валюте для будущих поддерживаемых
|
портфеля, валютной конвертации, учёта виртуальных позиций или заблокированных
|
||||||
представлений; публичного графика в текущем решении нет. Нет также
|
средств. Последний полный снимок сохраняется после перезапуска; выполнение
|
||||||
валютной конвертации, учёта виртуальных позиций или заблокированных
|
синхронизации рассчитано на один экземпляр backend. Действие «Обновить»
|
||||||
средств. Последний полный снимок сохраняется после перезапуска;
|
перечитывает зависимости открытого экрана независимо от их свежести.
|
||||||
обновлением личных данных владеет часовой обход, рассчитанный на один
|
|
||||||
экземпляр backend. Действие «Обновить» выполняет только локальное
|
|
||||||
перечитывание открытого экрана и не запускает работу с T-Bank.
|
|
||||||
|
|
||||||
Для проверки конкретной суммы используйте
|
Для проверки конкретной суммы используйте
|
||||||
[руководство по расхождениям](how-to/investigate-discrepancy.md).
|
[руководство по расхождениям](how-to/investigate-discrepancy.md).
|
||||||
|
|||||||
@@ -128,14 +128,6 @@ Instrument обогащают отображение Position или Event, но
|
|||||||
|
|
||||||
_Не использовать_: бумага, тикер, актив позиции.
|
_Не использовать_: бумага, тикер, актив позиции.
|
||||||
|
|
||||||
## Скринер акций
|
|
||||||
|
|
||||||
Подбор выпусков акций по заданным условиям из каталога T-Bank с указанием
|
|
||||||
времени получения списка. Скринер отличается от текстового поиска конкретного
|
|
||||||
инструмента, личного портфеля и подтверждения исполнимости сделки.
|
|
||||||
|
|
||||||
_Не использовать_: гарантия покупки, личная проверка доступа к сделке.
|
|
||||||
|
|
||||||
## Instrument Logo
|
## Instrument Logo
|
||||||
|
|
||||||
Имя файла бренда T-Bank для отображения Instrument в интерфейсе;
|
Имя файла бренда T-Bank для отображения Instrument в интерфейсе;
|
||||||
|
|||||||
+1
-12
@@ -20,12 +20,6 @@ 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), смысл дополнений — в
|
||||||
@@ -97,12 +91,7 @@ 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
@@ -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): рынок, личная позиция, история и события |
|
||||||
|
|
||||||
## Как связаны представления
|
## Как связаны представления
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "wealth-ledger-docs",
|
"name": "wealth-ledger-docs",
|
||||||
"version": "0.1.5",
|
"version": "0.1.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "wealth-ledger-docs",
|
"name": "wealth-ledger-docs",
|
||||||
"version": "0.1.5",
|
"version": "0.1.3",
|
||||||
"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
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wealth-ledger-docs",
|
"name": "wealth-ledger-docs",
|
||||||
"version": "0.1.5",
|
"version": "0.1.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "24.21.0"
|
"node": "24.21.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user