Files
specs/openspec/changes/archive/2026-11-02-account-top-positions/analysis/docs-impact.md
T
codex-bot 3821d9ed58
Specs security / security (push) Successful in 7s
Specs verify / verify (push) Successful in 14s
refactor: group canonical specs by domain and archive account-top-positions (#74)
2026-11-02 21:50:49 +03:00

27 KiB
Raw Blame History

Documentation Impact

Summary

Change account-top-positions (Issue WealthLedger/main#48) добавляет на страницу одного счёта вкладку «Концентрация» с разрезами «Акции», «Облигации», «Секторы», «Эмитенты», а в позиции Portfolio — сектор и эмитента (бренд актива). Для docs это значит:

  • В AS-IS появляются новые понятия и правила: вкладка, разрезы, «Прочее», сектор, эмитент (бренд актива во вкладке), правило 24 часов для сектора и бренда.
  • Сектор и бренд — исключение из правила «справочные сведения только онлайн» (ADR 019). Решение оформляется новым ADR 022; текст ADR 019 не переписывается, в его статус добавляется ссылка.
  • Хранение решено в design (B1): отдельная глобальная таблица TbankInstrumentClassification, не связанная с подключением. Её состав и поведение при отказах отражаются в containers.md и data-freshness.md.
  • Правки AS-IS — после реализации и её слияния в develop. До этого docs не описывает поведение, которого в системе нет.

Пути ниже — относительно корня workspace WealthLedger/; для docs-репозитория полный путь — docs/<path>.

Documentation Changes

Action Target Category Итоговое AS-IS Source Verification
Изменить docs/domains/portfolio/overview.md, разделы «Снимок и связанные области» и «Как читать экран» Domain На странице одного счёта рядом с «Позиции» есть вкладка «Концентрация». В ней четыре разреза: «Акции», «Облигации», «Секторы», «Эмитенты». По умолчанию открыт «Акции» и первая по ISO валюта. В каждом разрезе топ-5 элементов; при семи и более элементах остальные — в «Прочее», раскрытие не меняет топ-5. Суммы и доли — в одной валюте, конвертации нет. Вкладки нет в режиме «Все счета» и при загрузке, ошибке или пустом Portfolio. Вкладка не меняет вкладку по умолчанию. Деньги не входят в знаменатель долей (в отличие от «Структуры») specs/.../portfolio-concentration/spec.md (Вкладка, Состояния, Переключение, Начальное состояние, Одна валюта); proposal.md What Changes; design.md D8–D10 Сверка с мерджнутым frontend и итоговыми Specs; проверка ссылок
Добавить docs/domains/portfolio/concentration.md (новый файл, если правила не умещаются в overview.md; решение при написании) Domain / reference Состав разрезов по типам позиций; топ-5 и «Прочее»; группы «Сектор не указан», «Эмитент не указан»; значение government с подписью «Государственный сектор»; правила долей и одной валюты specs/.../portfolio-concentration/spec.md (Состав разрезов, Названия элементов); proposal.md Линк из overview.md и docs/README.md; markdownlint
Изменить docs/domains/portfolio/data-reference.md, таблица «Состав и денежные показатели»; раздел «Структура и доли» Reference Позиция получает sector (сектор T-Bank без перекодирования, пробелы обрезаны, пустое → null; только STOCK, BOND, FUND) и issuer (бренд актива T-Bank; null вне разрезов; фонды в разрез «Эмитенты» не входят). logoName не меняется. В «Структуре» отметить: знаменатель и валютные итоги включают деньги, вкладка «Концентрация» — нет specs/.../portfolio-view/spec.md «Нормализованный состав Portfolio» (PVΔ:3); data-mapping.md M1, M2; design.md D7 Сверка с кодом ответа и с OpenAPI, выпущенным backend; DTO не копируется
Изменить docs/domains/portfolio/flows/portfolio-loading.md, разделы «Основной обмен» и «Ошибки и результат для пользователя» Flow Сектор и бренд получаются в том же часовом обходе, в шаге до публикации Snapshot: после GetPortfolio и GetPositions. Первая попытка по позиции — не раньше чем через 24 часа после последнего успешного получения; пока значение не получено, попытка повторяется при каждом обходе. Ошибка получения не мешает публикации Snapshot и не меняет isStale и lastSuccessfulAt, кроме отказа token: он даёт 400 INVALID_TBANK_TOKEN без fallback. Сохранённое значение остаётся доступным. Обычный GET по-прежнему не обращается к T-Bank. Фраза «Metadata инструмента дополняет представление независимо» уточняется: сектор и эмитент входят в Snapshot PVΔ:104, PVΔ:141, PVΔ:156; failure-model.md; design.md B2, D1–D5 Сверка с таблицей исходов PVΔ:156 и с кодом после слияния
Изменить docs/integrations/tbank.md, таблица «Данные и ответственность»; раздел «Публичные логотипы» Integration Новые данные из T-Bank: сектор инструментов акций, облигаций и фондов (вызовы ShareBy, BondBy, EtfBy); бренд актива (uid и название) через GetAssetBy по asset_uid. Эмитент не выводится из названия, тикера или ISIN. Логотип по-прежнему приходит из metadata инструмента (logoName) и не равен эмитенту. Вызовы проходят через общий лимитер (по умолчанию 5/с) и ограниченную очередь data-mapping.md «Источники-кандидаты в T-Bank»; design.md B4, D6 Сверка с кодом T-Bank-клиента после слияния; ссылки на CDN не меняются
Изменить docs/architecture/cross-cutting/data-freshness.md, раздел «Клиентский и серверный снимки» (список данных SQLite) и абзац про часовой обход Architecture (cross-cutting) SQLite дополнительно хранит классификацию инструментов (сектор и бренд) в глобальной таблице TbankInstrumentClassification: она не принадлежит пользователю или подключению и не ограждается по connection revision. Каждое поле имеет свой возраст (sectorFetchedAt, brandFetchedAt). Классификация не входит в meta.dependencies и не меняет свежесть Snapshot. Прежнее утверждение «общие сведения об инструментах запрашиваются онлайн» получает оговорку про это исключение и ссылку на ADR 022 design.md Data / Storage Changes, D1, D4; design.md Cross-cutting «Freshness»; PVΔ:104, PVΔ:3 Сверка с миграцией Prisma после слияния; проверка ссылки на ADR 022
Изменить docs/architecture/containers.md, раздел «Хранимые данные и границы доступа» (абзац про portfolio и общие сведения) Architecture (data) Добавить: SQLite содержит таблицу TbankInstrumentClassification (провайдер, ключ инструмента, сектор с возрастом, uid актива и бренда с именем и возрастом). Данные публичные, без токена и позиций. Снимок Portfolio полей классификации отдельно не хранит: поля sector и issuer позиций заполняются из таблицы при публикации design.md Data / Storage Changes; B2; PVΔ «Ограничения доступа» Сверка с schema.prisma и миграцией после слияния
Изменить docs/glossary.md, блок Portfolio (после «Currency Instrument Position», до «Instrument»): новые термины Glossary См. раздел «Glossary / Navigation Impact» proposal.md; specs/.../portfolio-concentration/spec.md; решение владельца (3083) Формат: ## Термин, определение и «Не использовать»; ссылки на домен
Изменить docs/overview.md, таблица «Основные задачи пользователя», строка «Понять текущий состав инвестиций» Navigation Добавить задачу «увидеть, где сконцентрированы деньги: бумаги, секторы, эмитенты» со ссылкой на портфель proposal.md (Why) markdownlint, relative-links
Изменить docs/README.md, таблица «Предметные области», строка «Портфель» Navigation Строка «Позиции, остатки, суммы, структура и свежесть» дополняется концентрацией (и ссылкой на новый файл, если он появится) Как выше markdownlint, relative-links
Новый ADR docs/adr/022-stored-instrument-classification.md и строка в docs/adr/README.md ADR Фиксирует исключение: сектор и бренд актива хранятся как последнее известное значение с отдельным возрастом, а не запрашиваются онлайн. Область: сектор для STOCK/BOND/FUND, бренд актива; 24-часовой отсчёт; сохранение при ошибке; глобальная таблица без привязки к подключению design.md B1, D1–D2; PVΔ:104; ADR 019; решение владельца (3083) Номер и отсутствие дубликата проверить на момент записи; ссылки проходят
Изменить (связь) docs/adr/019-hourly-reads-and-online-instrument-reference.md, строка Status ADR Добавить: «дополнен ADR 022 в части сектора и бренда актива позиции». Текст решения 019 не переписывается docs/CONTRIBUTING.md («Подтверждённо заменённое решение связывается с новым, а не переписывается») Ссылка открывается; markdownlint
Изменить (условно) docs/domains/portfolio/all-accounts.md, раздел «Маршруты и навигация» Navigation Одна строка: вкладки «Концентрация» в общем режиме нет. Если владелец решит, что это не нужно описывать — не менять specs/.../portfolio-concentration/spec.md («Режим «Все счета»») Решение при написании

Что не меняется (и почему)

Target Причина
docs/architecture/containers.md, Mermaid-диаграмма Container и раздел «Контейнерная поставка» Новых внешних систем и контейнеров нет; T-Bank Brands CDN используется только для изображений, как и раньше
docs/architecture/context.md, Mermaid-диаграмма и текст Тот же набор внешних систем
docs/architecture/http-api.md Контракт генерирует backend (OpenAPI). Новые необязательные поля не копируются в docs
docs/domains/accounts/overview.md Перечня вкладок страницы счёта в docs нет; вкладка относится к портфелю
docs/domains/instruments/stocks.md, docs/domains/instruments/bonds.md Сектор и бренд показываются только во вкладке счёта. Файлы не читались целиком — проверить поиском «сектор» перед PR
docs/domains/portfolio/all-accounts.md (кроме условной строки выше) Общий режим без вкладки; новых маршрутов нет
docs/CHANGELOG.md Генерируется release-it из коммитов; вручную не править
docs/architecture/cross-cutting/ui-resilience.md Не читалось полностью. Проверить, описывает ли оно состояния страницы счёта

Diagram Promotion

Перенос диаграмм не требуется. По умолчанию перенос не делается (schema.yaml, docs-impact; docs/CONTRIBUTING.md).

  • analysis/ux-design.md, Mermaid flowchart «Страница счёта → Концентрация» — UI-поток этого change, не системная архитектура. В docs не переносится.
  • visuals/*.svg — материалы Visual Package; в docs не размещаются.
  • Существующие диаграммы (Container, Context, sequence подключения T-Bank) не меняются.
  • Sequence «часовой обход → классификация → Snapshot» в docs не добавляется: поток описан текстом в portfolio-loading.md. Если понадобится, её делает автор docs-PR по design.md B2.

ADR Decision

Практика ADR в docs есть: журнал docs/adr/, индекс в docs/adr/README.md, последний номер — 021, следующий — 022. Формат — по ADR 019: # NNN. Название, **Status:**, ## Decision, ## Consequences. Принятый ADR не переписывается; замена связывается ссылкой на новый (docs/CONTRIBUTING.md).

Решение владельца (3083): добавить ADR для хранения сектора и бренда как исключения из online-only справочных данных.

ADR 022 — docs/adr/022-stored-instrument-classification.md, статус Accepted. Содержание, подтверждённое источниками:

  • Context: ADR 019 (справочные сведения онлайн; старые строки не источник актуальности); PVΔ:104 (исключение для сектора и бренда); design B1 (общий metadata-кэш не подходит: Instrument не содержит сектора, brand — BrandData, а не Brand{uid,name}).
  • Decision: глобальная таблица TbankInstrumentClassification с последним известным значением сектора и бренда, возраст полей раздельно; обновление по правилу PVΔ:141 (не раньше 24 ч после последнего успешного получения); четыре исхода PVΔ:156; без привязки к пользователю и подключению.
  • Consequences: первый долговременный справочник T-Bank в системе; число вызовов T-Bank растёт при первом обходе (разовый всплеск, ограничен D6); отказ token обрабатывается как в обходе Portfolio; пересмотр, если появится второй потребитель (design ADR Candidates).
  • Альтернативы: design Solution Assessment, варианты B и C. В ADR описываются кратко, со ссылкой на design.

ADR 022 пишется в том же docs-PR, что и изменения AS-IS, или раньше — и тогда в статус ADR 019 добавляется ссылка в том же PR, что и ADR 022.

Glossary / Navigation Impact

Глоссарий (docs/glossary.md)

Новые термины — в блоке Portfolio (после «Currency Instrument Position», до «Instrument»). Формат: ## Термин, краткое определение, строка _Не использовать_.

Термин Что писать
Концентрация Вкладка страницы одного счёта с разрезами по бумагам, секторам и эмитентам текущего Portfolio. Ссылка на домен портфеля. Не «структура»
Разрез Одна из четырёх группировок вкладки «Концентрация»: набор элементов, на которые делится оценка позиций
Сектор Значение сектора T-Bank для позиций STOCK, BOND, FUND, без собственной классификации WealthLedger. Государственные облигации — значение government с подписью «Государственный сектор»
Эмитент В разрезе «Эмитенты» вкладки «Концентрация» — бренд актива по данным T-Bank. Фонды в разрез не входят. Оговорка (решение владельца 3083): в этом разрезе слово означает бренд актива T-Bank, а не юридического эмитента ценной бумаги. Строка «Не использовать»: юридический эмитент, эмитент рейтинга (см. рейтинг выпуска НКР)
«Прочее» Группа остальных элементов разреза при семи и более элементах. Это UI-подпись: описывается в доменной странице, в глоссарии — одна строка-ссылка

Владелец оставил термин «Эмитенты». Конфликт с юридическим эмитентом в NKR, ADR 013, context.md и bonds.md сохраняется; оговорка в глоссарии — единственное место, где он снимается. Остальные страницы, использующие «эмитент» в значении рейтинга или выпуска, не меняются.

Не добавлять отдельными записями: «Сектор не указан», «Эмитент не указан», «Государственный сектор» — UI-подписи, описываются в доменной странице.

Связанная существующая запись: «Instrument Logo» (строка про logoName) — после change явно указать, что логотип не равен эмитенту.

Навигация

  • docs/domains/portfolio/overview.md — главная страница для концентрации; ссылки на data-reference.md и новый файл (если будет).
  • docs/overview.md, docs/README.md — строки из таблицы изменений.
  • docs/architecture/README.md — новых вопросов не добавляется.
  • docs/adr/README.md — строка 022 в индексе.

Порядок относительно реализации

Порядок из docs/CONTRIBUTING.md («Фазы работы»), docs/AGENTS.md и правила AS-IS. Design задаёт выкат: backup, миграция CREATE TABLE, backend, публикация OpenAPI, frontend (design.md, Migration / Rollout).

  1. Сейчас (G2 approved, G3 — design package): AS-IS страницы не меняются. Создать пункты [docs] в tasks.md по таблице выше.
  2. Во время реализации: черновики текста допустимы в issue-linked ветке docs от develop. ADR 022 — в статусе Accepted (решение принято владельцем 3083).
  3. Слияние в develop docs-PR — после слияния backend и frontend и проверки на окружении: AS-IS-тексты не должны обещать поведение, которого в develop нет. ADR 022 можно слить раньше, если его текст не описывает поведение, а фиксирует решение.
  4. Перед завершением: сверка «текст ↔ код ↔ Specs»; docs-sync-audit или ручная проверка; проверки из следующего раздела.

Заголовок PR — conventional commit (docs/commitlint.config.cjs; CI commits.yml запускает commitlint --strict). В описании PR — ссылка на Issue #48 и change-id.

AS-IS правила

  • Docs описывает только поведение, которое есть в develop и проверено. Спецификация change не копируется в docs как требование.
  • Формулировки «будет», «планируется» в AS-IS-страницах не используются.
  • Текущие утверждения, которые станут неверными после change (исправлять только после реализации):
    • docs/architecture/cross-cutting/data-freshness.md — список данных SQLite и онлайн-правило для инструментов;
    • docs/domains/portfolio/flows/portfolio-loading.md — «Metadata инструмента дополняет представление независимо»;
    • docs/adr/019-… — онлайн-правило: исключение описывает ADR 022; текст 019 не переписывать;
    • docs/domains/portfolio/data-reference.md — «Структура» и «Концентрация» не должны выглядеть одним показателем.
  • Один факт — один источник: правила сектора и бренда живут в portfolio-view Specs; docs ссылается на них, а таблицы исходов из failure-model.md не копирует.
  • Имена RPC T-Bank в docs упоминаются только как категории источников; точный контракт — код и design.md.

Проверки

Из корня docs (docs/), по docs/CONTRIBUTING.md и docs/AGENTS.md:

nvm use --silent        # если nvm не загружен, сначала загрузить $HOME/.nvm/nvm.sh (см. корневой AGENTS)
npm ci                  # если зависимости не установлены
npm run verify          # = npm run lint && git diff --check
  • npm run lint: markdownlint по **/*.md (кроме node_modules и CHANGELOG.md) с правилом относительных ссылок; отдельно CHANGELOG.md.
  • Коммит: npm run commitlint -- --strict.
  • Ручные проверки, которые lint не делает: якоря в ссылках; смысловая сверка с кодом и Specs; маршрут чтения в README.md; новый файл достижим из индекса.
  • Рендер Mermaid не проверяется ни одним инструментом из package.json. Если меняется диаграмма, отмечать «не проверено рендером».
  • Для ADR 022: номер, отсутствие дубликата в docs/adr/README.md, ссылка из ADR 019.

В этой задаче проверки не запускались: правок в docs нет.

Открытые вопросы и расхождения

  1. Конфликт термина «эмитент» сохраняется вне вкладки: NKR, ADR 013, context.md, bonds.md используют слово для юридического эмитента. Оговорка в глоссарии снимает конфликт только для вкладки; остальные страницы — решение владельца, если оно понадобится.
  2. Конфликт с ADR 019 снимается ADR 022 (решение 3083). Текст ADR 019 остаётся историческим.
  3. Не полностью прочитаны: docs/domains/instruments/stocks.md, bonds.md, docs/architecture/cross-cutting/ui-resilience.md, docs/integrations/README.md. Проверить поиском перед PR.
  4. Основание решения 3083 в этом файле не цитируется дословно: текст комментария Issue не читался в этой задаче. Перед написанием ADR 022 сверить формулировку с комментарием.
  5. Вне scope: docs/code-quality-review.md лежит в корне docs, хотя docs/AGENTS.md запрещает аудиты в docs. Не трогается.