1117 lines
120 KiB
Markdown
1117 lines
120 KiB
Markdown
Выполнены implementation-owned задачи 1.1–7.5 (27/27). Archive не выполнялся. Текущее evidence — в checkpoint ниже.
|
||
Входы: [Design revision 1](design.md), включая полностью inline UI/UX package,
|
||
и [delta specs](specs/tbank-data-sync/spec.md). Перед работой в каждом repo
|
||
прочитать его AGENTS и применимый routing; перед Node — местный `nvm use --silent`.
|
||
Ни одна задача не требует изменения root или чтения соседнего checkout в CI.
|
||
|
||
## 1. Основание и сохраняемая модель
|
||
|
||
- [x] 1.1 [backend] Применить Solution Assessment: использовать текущие Prisma/SQLite/TbankClient, зафиксировать baseline HTTP/RPC и подготовить изолированные исходные данные профиля Design без новой очереди или scheduler.
|
||
- **Covers:** `N/A` — техническое основание storage/concurrency решения и сопоставимых измерений из Design; самостоятельного пользовательского поведения не добавляет.
|
||
- **Verification:** сохранить версии runtime, hardware, объём/распределение fixture и числа RPC/latency исходного navigation trace; проверить, что тесты не используют рабочую SQLite и реальные token; проверить существующие owners и отсутствие добавленной инфраструктуры.
|
||
|
||
- [x] 1.2 [backend] После 1.1 добавить additive Prisma migration для connection revision, membership, private datasets и последних полных прогнозов, общих инструментальных источников, coverage/work/staging с описанными unique keys и индексами.
|
||
- **Covers:** `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Общие данные инструментов отделены от личных`.
|
||
- **Verification:** `npx prisma validate`, generate/typecheck и migration на пустой и заполненной временной SQLite; автоматическая проверка integrity/FK, сохранности User/Session/TbankConnection/manual cards и исходных зашифрованных token; decimal round-trip без float; подтверждение ключей/индексов и невозможности дублирующей операции.
|
||
|
||
- [x] 1.3 [backend] После 1.2 реализовать локальный membership owner и атомарную границу PUT/DELETE подключения, включая использование списка успешной проверки token и publication fence по revision/attempt.
|
||
- **Covers:** `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`; `brokerage-accounts` — `Состояния недоступности списка счетов`.
|
||
- **Verification:** реальные SQLite/HTTP проверки двух пользователей, unknown/empty/stale membership, closed/unsupported/removed account, invalid token, failed replacement и late completion после replace/delete; на warm access path spy фиксирует 0 GetAccounts до HTTP-ответа; данные/coverage/errors старой revision не публикуются.
|
||
|
||
## 2. Интервалы и выполнение запрошенной работы
|
||
|
||
- [x] 2.1 [backend] После 1.2–1.3 реализовать операции staging → atomic reconciliation → coverage/dataRevision с обязательным исходным ID и локальной фильтрацией границ.
|
||
- **Covers:** `tbank-data-sync` — `Сверка операций сохраняет идентичность и прежний результат`; `tbank-data-sync` — `Полнота подтверждается успешным покрытием интервалов`; `brokerage-account-ledger` — `Ledger entries preserve broker operation meaning`.
|
||
- **Verification:** SQLite integration на нескольких страницах: одинаковый ID, изменённые amount/date/state, исчезнувшая операция, identical duplicate, conflicting duplicate, missing ID/cursor и сбой средней страницы; полная старая выборка/сумма/время не меняются до commit, удаление ограничено account/interval/predicate, частичный income-filter не подтверждает весь счёт. Refresh полного квартала/all с ошибкой второго месяца сохраняет весь прежний результат до атомарного commit publication group.
|
||
|
||
- [x] 2.2 [backend] После 2.1 реализовать durable intent и in-process выполнение с coalescing, priority, ограниченной подачей RPC и request-only recovery по processRunId/attemptId.
|
||
- **Covers:** `tbank-data-sync` — `Прогресс переживает перезапуск и одновременные запросы`; `tbank-data-sync` — `Обновление запускается только запросом с учётом свежести`.
|
||
- **Verification:** автоматические гонки 20 одинаковых запросов, пересечения диапазонов и stale attempt; kill/restart между страницами и между stage/publish; без нового запроса 0 запусков, следующий запрос начинает незавершённое окно с первой страницы без дублей; после terminal failure нет retry loop; existing limiter/retry bounds сохраняются.
|
||
|
||
- [x] 2.3 [backend] После 2.2 реализовать planner экранных зависимостей, TTL и первичной догрузки истории с учётом календарей и unknown lower bound.
|
||
- **Covers:** `tbank-data-sync` — `Первая загрузка приоритизирует экран и продолжает историю`; `tbank-data-sync` — `Полнота подтверждается успешным покрытием интервалов`; `tbank-data-sync` — `Ручное обновление ограничено текущим экраном`.
|
||
- **Verification:** controlled-clock сценарии 59/60, 299/300 и 86399/86400 секунд; повтор current `to=now` через секунду не создаёт RPC и сохраняет asOf; selected/previous/yearAgo выполняются до старой истории; новый видимый пропуск обгоняет pending backfill; Moscow/UTC boundary, конец месяца/года/февраля и незагруженный хвост; openedOn отсутствует — coverage явно ограничена, вся история не объявлена полной. Зафиксировать проверенные source boundary semantics без выдуманного default `from`.
|
||
|
||
## 3. Локальные владельцы данных и производные результаты
|
||
|
||
- [x] 3.1 [backend] После раздела 2 перевести accounts, portfolio и все consumers личных позиций на общий persistent portfolio/membership owner.
|
||
- **Covers:** `brokerage-accounts` — `Список активных брокерских счетов`; `portfolio-view` — `Получение Portfolio выбранного Brokerage Account`; `portfolio-view` — `Свежесть и fallback полного Portfolio Snapshot`; `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`.
|
||
- **Verification:** configured HTTP/SQLite сценарии warm/cold/empty/stale portfolio, independent summary failure, all-account membership revision, отсутствующий metadata fallback и known access error; прежние Money/order/unsupported account правила сохранены; portfolio старше пяти минут остаётся доступен при допустимом доступе без блокирующих RPC.
|
||
|
||
- [x] 3.2 [backend] После 2.1–2.3 перевести ledger и instrument personal history на локальные фильтры, детерминированную пагинацию и revision-bound cursor; убрать обязательный RAM-page TTL read path.
|
||
- **Covers:** `brokerage-account-ledger` — `User can retrieve an account ledger`; `brokerage-account-ledger` — `User can browse a filtered ledger`; `brokerage-account-ledger` — `Кэш страниц журнала ограничивает локальные ресурсы`.
|
||
- **Verification:** HTTP/DB cursor tests на равных timestamps, нескольких счетах, эквивалентных filters, connection/membership/rowset change, invalid cursor и `hasNext=false` при неполном coverage; categories/UID/page limit не создают полноту; повторная старая страница не вызывает RPC; personal instrument force удаляет только записи своего predicate.
|
||
|
||
- [x] 3.3 [backend] После 3.2 перевести income/summary на сохранённые операции и раздельную готовность selected/previous/yearAgo, сохранив точные денежные правила.
|
||
- **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries`.
|
||
- **Verification:** денежные integration tests с несколькими валютами, отрицательной корректировкой, одинаковыми ID одного/разных счетов, empty complete и missing periods; selected complete/previous loading не даёт нулевую базу; all aggregation требует каждого счёта; обновлённая запись пересчитывается один раз; новый period не возвращает старый под новой подписью.
|
||
|
||
- [x] 3.4 [backend] После 2.2–2.3 разделить shared catalog/metadata/company/quotes и личные projections; сохранить existing UID/FIGI/ticker lookup и источники bond metrics.
|
||
- **Covers:** `tbank-data-sync` — `Общие данные инструментов отделены от личных`; `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Обновление запускается только запросом с учётом свежести`.
|
||
- **Verification:** два пользователя используют сохранённый общий источник без повторного RPC и без передачи private fields/errors; каталог без enrichment не выдаёт ложный пустой поиск; свежий query SBER не подтверждает unknown GAZP, повтор того же query использует сохранённый discovery; company/fundamentals included; minute/day TTL независимы; stale initiating connection не публикует даже общий результат; bond quote percent/nominal/ACI и optional MOEX failures сохраняют прежний смысл.
|
||
|
||
- [x] 3.5 [backend] После 3.4 реализовать durable candle coverage, mutable tail и portfolio-instrument prefetch через тот же planner.
|
||
- **Covers:** `tbank-data-sync` — `Завершённость свечей подтверждается источником`; `tbank-data-sync` — `Первая загрузка приоритизирует экран и продолжает историю`.
|
||
- **Verification:** автоматические window tests: 365-day seams/dedupe, complete candle без RPC после restart, old incomplete candle после полуночи, утреннее пустое окно → новая свеча, закрытое пустое окно, missing historyFrom, ошибка ручной перечитки; prefetch только бумаг текущего portfolio, открытие другого инструмента запускает его историю.
|
||
|
||
- [x] 3.6 [backend] После 3.1 и 3.4 перевести instrument payouts и account upcoming events на общие сохранённые календари и локальные personal estimates, устранив отдельный synchronous portfolio fetch.
|
||
- **Covers:** `brokerage-account-upcoming-events` — `User can retrieve upcoming events for an account`; `brokerage-account-upcoming-events` — `Forecasts preserve event meaning and uncertainty`; `brokerage-account-upcoming-events` — `Upcoming events use complete source results`; `tbank-data-sync` — `Общие данные инструментов отделены от личных`.
|
||
- **Verification:** полные/неполные/пустые календари, cancelled dividends, offer без суммы, MOEX missing block, stock/bond source identity, holdings-dependent estimate и отсутствие private values в shared tables; новый portfolio с новой бумагой + ошибка её календаря + restart возвращает прежний полный прогноз/estimate того же scope с исходным временем; новый period/membership не получает чужой snapshot. Events refresh сохраняет применённые from/to.
|
||
|
||
## 4. Публичный API и передача контракта
|
||
|
||
- [x] 4.1 [backend] После раздела 3 оформить envelope/meta/dependency coverage всех существующих data GET, observe mode, screen-scoped POST sync и авторизованный GET status в DTO/controllers/Swagger.
|
||
- **Covers:** `tbank-data-sync` — `Ручное обновление ограничено текущим экраном`; `tbank-data-sync` — `Интерфейс различает свежесть полноту и состояние работы`; `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`.
|
||
- **Verification:** configured HTTP contract tests для каждого route family, включая accounts/search arrays, stock company, quotes/candles/payouts и all scope; `202` не означает завершение, malformed descriptor отклонён, чужой job 404; `sync=observe`/status не создают RPC при stale/missing/failed; generation отсутствует в API/errors/logs и декодируемых cursors; Problem Details и nullable previous/yearComparison/summary dependency states соответствуют Design. Empty coverage completion меняет stateVersion без изменения pagination revision.
|
||
|
||
- [x] 4.2 [backend] После 4.1 опубликовать сгенерированный OpenAPI artifact для frontend и проверить runtime parity, не превращая specs в editable HTTP-контракт.
|
||
- **Covers:** `N/A` — передача изменённого публичного контракта из Contract Gate Decision, без самостоятельной бизнес-возможности.
|
||
- **Verification:** `npm run test:openapi-contract` и сформированный backend-owned artifact; новые DTO/status/errors представлены, secret examples отсутствуют; artifact передаваем явно, backend CI не читает соседний frontend.
|
||
|
||
- [x] 4.3 [frontend] После 4.2 принять предоставленный snapshot, выполнить локальную генерацию и адаптировать entity query owners, включая observe reads и connection/session fences.
|
||
- **Covers:** `frontend-data-resilience` — `Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio`; `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`.
|
||
- **Verification:** `npm run openapi:generate`, `npm run openapi:check`; typecheck всех consumers, включая breadcrumbs, document title и scope switch; MSW/RTL доказывает одну canonical cache identity для ordinary/observe, поздние data/status ответы старой connection/session игнорируются, all financial caches очищаются успешной mutation и сохраняются после неуспешной.
|
||
|
||
## 5. Экранные состояния и ручное обновление
|
||
|
||
- [x] 5.1 [frontend] После 4.3 добавить page-owned screen descriptor и observer запрошенной работы по inline UI/UX package revision 1; разделить transport и source lifecycle.
|
||
- **Covers:** `tbank-data-sync` — `Интерфейс различает свежесть полноту и состояние работы`; `tbank-data-sync` — `Ручное обновление ограничено текущим экраном`; `frontend-data-resilience` — `Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio`.
|
||
- **Verification:** MSW/RTL controlled-clock checks: manual refresh обходит TTL только текущего scope; status poll + observe не создаёт новую работу даже после истечения минуты; observer прекращается при terminal/уходе/logout, active duplicate button недоступна; empty coverage completion отображается до завершения дальней истории; reverse-order observe ответы не откатывают данные/доступ; old data/timestamp остаются при transient failure, failed force до TTL сохраняет fresh, known access error очищает personal view.
|
||
|
||
- [x] 5.2 [frontend] После 5.1 адаптировать accounts/account/all screens и независимые overview sections к server completeness/freshness и scoped refresh.
|
||
- **Covers:** `brokerage-accounts` — `Экран списка брокерских счетов`; `brokerage-accounts` — `Клиентские состояния ошибки списка счетов`; `portfolio-view` — `Состояния и ошибки Portfolio на клиенте`; `brokerage-account-ledger` — `Account overview includes recent ledger events`; `brokerage-account-income-analytics` — `Account overview has an independent current-month income summary`; `brokerage-account-upcoming-events` — `Account overview includes upcoming events`.
|
||
- **Verification:** RTL scenarios unknown/complete-empty accounts, independent summary staleness, portfolio + recent ops + income + events partial states, сохранённые суммы при failed refresh, 404/invalid token, новая membership в all; кнопка обновляет dependencies overview, не только portfolio.
|
||
|
||
- [x] 5.3 [frontend] После 5.1 адаптировать operations/income/events pages: отдельная полнота периодов и comparisons, cursor recovery и сохранение applied filters.
|
||
- **Covers:** `brokerage-account-ledger` — `User can browse a filtered ledger`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning`; `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries`; `brokerage-account-upcoming-events` — `Account page presents an upcoming events list`.
|
||
- **Verification:** RTL/MSW: partial empty не показывает «операций/доходов нет», selected готов до comparison без нулевой базы, отрицательная корректировка/одна карточка на identity, INVALID_OPERATIONS_CURSOR возвращает первую страницу с сохранением фильтров, смена периода не переименовывает старые суммы; полный старый events result виден с ошибкой обновления.
|
||
|
||
- [x] 5.4 [frontend] После 5.1 адаптировать stock/bond search и detail sections: quote, company/metrics, candles, position, payouts и personal history к общим статусам и текущему screen scope.
|
||
- **Covers:** `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Завершённость свечей подтверждается источником`; `frontend-data-resilience` — `Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio`.
|
||
- **Verification:** section-adapter и page integration tests различают missing/partial/complete-empty/stale/failed, неполные свечи и личные estimates; refresh сохраняет выбранный график/UID и обновляет показанную personal history, не весь каталог; metadata completion не меняет личную cache boundary.
|
||
|
||
## 6. Доказательства корректности и быстродействия
|
||
|
||
- [x] 6.1 [backend] После раздела 4 выполнить интегрированный crash/durability/rollback прогон на заполненной изолированной SQLite, расширив существующий подход сохранности данными T-Bank.
|
||
- **Covers:** `tbank-data-sync` — `Прогресс переживает перезапуск и одновременные запросы`; `tbank-data-sync` — `Сверка операций сохраняет идентичность и прежний результат`; `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`.
|
||
- **Verification:** сохранить runnable DB/HTTP tests для kill-before/after-publish, concurrent readers, membership change, replace/delete и shared result fence; подтвердить Rollback Contract без потери ручных карт и новых данных; unit mocks не заменяют реальные транзакции и reopen DB.
|
||
|
||
- [x] 6.2 [backend] После 6.1 измерить HTTP budget и RPC reduction на профиле Design с задержанным/отказывающим upstream и одинаковым baseline trace из 1.1.
|
||
- **Covers:** `tbank-data-sync` — `Быстродействие и сокращение запросов проверяются измерениями`; `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Обновление запускается только запросом с учётом свежести`.
|
||
- **Verification:** ≥100 запросов каждой указанной группы, 10 concurrent clients, p50/p95/p99/max/размеры ответов/hardware; цель p95 ≤500 мс, отдельно первый read после restart; fresh RPC=0, старые полные intervals RPC=0, 20 одинаковых stale requests=1 логический проход/dependency, завершённая работа без нового запроса RPC=0. Показать old/new counts и снижение; провал бюджета не объявлять успехом и не менять порог без явного решения.
|
||
|
||
- [x] 6.3 [frontend] После раздела 5 проверить inline UI/UX package revision 1 в браузере и сохранить уместные состояния в существующих stories на вымышленных данных.
|
||
- **Covers:** `tbank-data-sync` — `Интерфейс различает свежесть полноту и состояние работы`; `brokerage-accounts` — `Экран списка брокерских счетов`; `portfolio-view` — `Состояния и ошибки Portfolio на клиенте`; `brokerage-account-upcoming-events` — `Account page presents an upcoming events list`.
|
||
- **Verification:** journey accounts → account/all → ledger → income/comparison → events → stock/bond: cold, complete, partial, stale, failure, force refresh, leave/reopen, connection replacement; 320/375 px и широкий экран, длинные суммы, keyboard/focus, polite announcements, busy/skeleton/reduced motion. Browser evidence дополняет tests; Storybook build не доказывает состояния.
|
||
|
||
## 7. Документация и итоговые gates
|
||
|
||
- [x] 7.1 [docs] После подтверждённой реализации обновить as-built storage/access/freshness, инвестиционные flows, public API handoff и термин полноты, сохранив ADR как историю принятого решения.
|
||
- **Covers:** `N/A` — delivery объяснений поставленной архитектуры из Design, без параллельного источника требований.
|
||
- **Verification:** сверить architecture/containers, cross-cutting data-freshness/ui-resilience, http-api, integrations/tbank, domains accounts/operations/portfolio/income/instruments и glossary со всеми delivered flows; обновить отметку отсутствующей реализации ADR 017 только по факту поставки, сохранить исторические решения и чужие изменения. Пути README → тема → термин/API существуют.
|
||
|
||
- [x] 7.2 [backend] После 6.1–6.2 выполнить canonical gate для итогового backend и передать финальный OpenAPI artifact при отличиях от 4.2.
|
||
- **Covers:** `N/A` — canonical backend verification из Delivery Map и Contract Gate Decision; не отдельное поведение.
|
||
- **Verification:** `npm ci`, `npm run verify`, `npm run test:openapi-contract`; результаты обязательных DB/HTTP/latency checks относятся к тому же итоговому состоянию. Type/lint/build не объявляются доказательством migration/concurrency или latency.
|
||
|
||
- [x] 7.3 [frontend] После 6.3 и финального artifact backend выполнить canonical frontend gate для итоговых types/queries/UI/stories.
|
||
- **Covers:** `N/A` — canonical frontend verification изменённого API/UI package из Delivery Map, без самостоятельной бизнес-возможности.
|
||
- **Verification:** `npm ci`, `npm run verify`, включая локальный OpenAPI drift; браузерные и boundary checks должны относиться к итоговому коду. Frontend CI использует свой snapshot, а не checkout backend.
|
||
|
||
- [x] 7.4 [docs] После 7.1 выполнить canonical docs gate и смысловую проверку изменённых маршрутов чтения.
|
||
- **Covers:** `N/A` — проверка связности as-built documentation из Delivery Map, без новых требований.
|
||
- **Verification:** `npm run verify`, проверка новых/изменённых ссылок и терминов; если изменена диаграмма, проверить её renderer либо явно назвать ограничение. Не выдавать Markdown lint за семантическое подтверждение.
|
||
|
||
- [x] 7.5 [specs] После implementation-owned задач сверить выполненный результат с каждой delta requirement и обновить этот Tasks по наблюдённым результатам без преждевременного archive/main-spec sync.
|
||
- **Covers:** `N/A` — поддержание существующего SDD change и traceability реализации из Delivery Map; новых behaviors или отдельного журнала доказательств не создаёт.
|
||
- **Verification:** все 35 delta requirement headings, включая REMOVED, имеют выполненные задачи и подходящее evidence; `npm run verify`, `openspec schema validate wealth-ledger-sdd --verbose`, `openspec validate persist-tbank-data --type change --strict --store wealth-ledger-specs`, `openspec validate --specs --strict --store wealth-ledger-specs`; проверить новые файлы, ссылки и diff. Structural success не означает реализации или approval.
|
||
|
||
Независимое review и последующее завершение lifecycle не маскируются задачами,
|
||
которые implementation agent может закрыть самостоятельно. Эта подготовка
|
||
не разрешает менять приложение, применять миграцию к рабочей БД или
|
||
архивировать change; текущий результат — комплект для начала реализации.
|
||
|
||
## Implementation checkpoint — 2026-09-24
|
||
|
||
Пользователь разрешил Apply утверждённых артефактов, включая изменения приложения,
|
||
публичного API и документации. Архивирование не входит в текущую работу.
|
||
|
||
- Completed: 0/27. Задача 1.1 выполнена частично; checkbox не установлен.
|
||
- Backend: ветка `codex/persist-tbank-data` от полученного `origin/develop`
|
||
`0862d56c4e4d9dd554556c3992cc073193020ff1`. Production source/schema не изменены.
|
||
Добавлены `test/tbank-read-baseline.e2e-spec.ts` и
|
||
`test/fixtures/tbank-read-baseline.json` с исходным HTTP trace и результатами.
|
||
- Наблюдённый baseline: временная SQLite со штатными migrations, синтетическое
|
||
подключение, 3 счёта × 100 000 доступных upstream операций, 200 инструментов;
|
||
7 групп × 100 чтений, 10 клиентов. Node v24.21.0, Apple M1 Pro,
|
||
10 CPU, 32 GiB. Счётчики считают вызовы TbankClient, а не реальные transport RPC.
|
||
p95 client end-to-end: accounts 33.05 мс, portfolio 15.21 мс,
|
||
all portfolio 30.39 мс, ledger 13.17 мс, all ledger 16.20 мс,
|
||
income 2345.84 мс, all income 7128.47 мс. Полные percentile/size/counters
|
||
сохранены в JSON; это исходная реализация и не доказательство новой модели.
|
||
- Наблюдённые проверки: backend `npm run build`, `npm run typecheck:test`,
|
||
targeted ESLint, `npm run verify` (35 suites, 257 tests) — success;
|
||
`node test/sqlite.cjs tbank-read-baseline.e2e-spec.ts` — success (1 test).
|
||
HTTP runner потребовал разрешённый loopback listener вне sandbox.
|
||
Рабочая пользовательская БД и реальные credentials не использовались.
|
||
- Specs: `npm run verify`, native schema validation, strict change validation
|
||
с `--store wealth-ledger-specs` и strict validation всех 25 main specs — success.
|
||
Повтор `npm ci` с сетевым доступом завершился HTTP 502 настроенного Nexus
|
||
для `undici-types-8.9.0.tgz`; dependencies/lockfile не менялись.
|
||
- Backend `npm ci` после проверок также завершился HTTP 502 Nexus для
|
||
`zeptomatch-2.1.0.tgz`. Установка могла оставить неполный node_modules;
|
||
успешный verify выше относится к прежнему установленному окружению.
|
||
Воспроизводимая установка и canonical gate текущей поставки не закрыты.
|
||
- Remaining: задачи 1.1–7.5. Baseline пока не включает market/candles/payouts,
|
||
delayed/failing transport, профиль 4 CPU / 8 GiB или заполненные новые таблицы.
|
||
Миграция, новая модель чтения, frontend/API handoff и as-built docs не реализованы.
|
||
- Next implementation outcome: закончить 1.1 полным воспроизводимым trace
|
||
профиля Design и подготовкой fixtures, затем переходить к additive migration 1.2.
|
||
|
||
### Продолжение установки
|
||
|
||
Повторные установки через Nexus снова получили HTTP 502. Выполнен успешный
|
||
`npm ci --registry=https://registry.npmjs.org --replace-registry-host=never`
|
||
в backend (1065 packages) и specs (239 packages), с прежними lockfile/integrity.
|
||
Manifest, lockfile и постоянная registry configuration не менялись.
|
||
Это восстанавливает локальное окружение, но не исправляет доступность Nexus.
|
||
|
||
|
||
### Checkpoint после продолжения Apply
|
||
|
||
- Completed: 1.1, 1.2 (2/27); remaining: 1.3–7.5. Предыдущий checkpoint
|
||
описывает предыдущий прогон, а не текущее состояние реализации.
|
||
- 1.1: расширенный baseline успешно измерил 23 группы × 100 чтений,
|
||
10 concurrent clients, включая stock/bond detail, quote, company/metrics,
|
||
year/all candles, payouts/search и account/all events. Fixture предоставляет
|
||
3 × 100 000 операций и 200 × 5000 свечей; все внешние providers синтетические.
|
||
Полный trace/percentiles/bytes/счётчики вызовов внешних clients сохранены
|
||
в backend `test/fixtures/tbank-read-baseline.json`. Это измерение исходной
|
||
модели на фактическом host, не доказательство budget новой модели 6.2;
|
||
transport limiter/retries исключены из этих счётчиков.
|
||
- 1.2: добавлены Prisma models и migration `20260924170000_persist_tbank_data`.
|
||
Revision присваивается существующим подключениям без изменения ciphertext;
|
||
SQLite rebuild подключения и новые таблицы выполняются одной транзакцией.
|
||
Private membership/portfolio/operations/coverage/forecasts/work/staging
|
||
связаны FK с revision; shared metadata/lookups/catalog/sources/candles/coverage
|
||
хранятся отдельно. Decimal payload и candle close остаются строками.
|
||
- Наблюдённые проверки 1.2: Prisma validate/generate, app/test typechecks,
|
||
`node test/sqlite.cjs tbank-migration.e2e-spec.ts` (2 passed).
|
||
Проверены пустая/заполненная SQLite, reopen, integrity/FK, сохранность старых
|
||
User/Session/connection/manual-card records, unique operation identity,
|
||
одинаковые ID разных счетов, decimal round-trip, индекс чтения, отказ позднего
|
||
staging attempt, cascade private rows и сохранение shared candle.
|
||
- 1.3 частично: PUT повторно использует accounts из validateToken, атомарно
|
||
заменяет connection/private rows и публикует membership. Local access method
|
||
не расшифровывает token и не делает RPC; различает unknown/empty/stale и
|
||
известный invalid token. `node test/sqlite.cjs tbank-connection.e2e-spec.ts`
|
||
(3 passed) проверяет HTTP auth, two users, failed replacement, DB rollback,
|
||
revision rotation и поздние private writes после replace/delete.
|
||
Известный invalid token блокирует и существующий HTTP accounts read до RPC;
|
||
финальный повтор HTTP suite (постоянный loopback listener) и verify прошёл.
|
||
Data GET ещё используют прежние owners; общий publication fence и discovery
|
||
через coordinator ещё не реализованы. Checkbox 1.3 не установлен.
|
||
- Итоговый backend `npm run verify`: 34 suites / 253 tests passed.
|
||
`npm run test:durability -- /tmp/wealthledger-tbank-rollback.PuzfjF` passed
|
||
на отдельной предыдущей сборке из `0862d56` и временной SQLite: manual data,
|
||
restart, rollback/return и backup/restore сохранены. Этот прогон не закрывает
|
||
задачу 6.1 о новых datasets и worker crash; результатов для неё пока нет.
|
||
- Frontend, docs, публичный envelope и OpenAPI handoff не изменены.
|
||
Рабочая пользовательская БД не использовалась. Change не архивирован.
|
||
- Next implementation outcome: завершить 1.3 — membership discovery/publication
|
||
с transaction fence текущей revision/attempt, затем staging/reconciliation 2.1.
|
||
|
||
### Checkpoint — membership publication и операции staging
|
||
|
||
- Completed остаётся 2/27. В 1.3 добавлена транзакционная публикация membership
|
||
через существующий access owner: revision/attempt fence, сохранение datasets
|
||
неизменных accounts, cascade удалённых accounts, отказ устаревшему invalid-token
|
||
результату. Отдельный coordinator ещё не подключён; checkbox не изменён.
|
||
- Начата persistence boundary 2.1: concrete operations repository сохраняет
|
||
страницы и continuation progress в SQLite staging, требует исходный ID,
|
||
проверяет pagination и противоречащие payload, локально фильтрует `[from,to)`.
|
||
Publication group обновляет операции/coverage всех accounts и intervals одной
|
||
транзакцией; instrument predicate ограничивает удаления и coverage.
|
||
operationsRevision изменяется только вместе с rowset, один раз на account.
|
||
- Наблюдённые проверки: `node test/sqlite.cjs tbank-connection.e2e-spec.ts`
|
||
— 4 passed; `node test/sqlite.cjs tbank-operations-persistence.e2e-spec.ts`
|
||
— 4 passed. Проверены rollback неполной группы, отрицательная корректировка,
|
||
одинаковый ID разных accounts, repeated/missing cursor, отсутствие ID,
|
||
exact upper boundary, конфликт версий между intervals, predicate isolation,
|
||
прежняя attempt, concurrent read отдельным SQLite connection и reopen.
|
||
Использованы только изолированные временные SQLite.
|
||
- Backend `npm run verify` прошёл (34 suites / 253 tests, lint, typechecks, build).
|
||
Это проверка текущего промежуточного состояния, не финальный gate задачи 7.2.
|
||
- Оставшиеся ограничения: HTTP owners ещё не читают новые datasets;
|
||
worker/coalescing/recovery и interval planner не реализованы. Repository
|
||
publication пока использует построчные Prisma operations; производительность
|
||
на 300 000 строк и budget 500 мс не подтверждены. Проверка kill процесса,
|
||
shared publication fence и полный Rollback Contract остаются в 6.1–6.2.
|
||
Frontend/docs и публичный API не изменены, OpenAPI handoff не выполнялся.
|
||
|
||
### Checkpoint — request-driven operations worker
|
||
|
||
- Реализован следующий backend этап 2.1–2.2: operations worker получает token
|
||
только для действующей revision/attempt, сохраняет intent и staging progress,
|
||
загружает EXECUTED pages через прежний TbankClient и публикует coverage вместе
|
||
с завершением работы. Уже полное покрытие автоматически требует атомарной
|
||
повторной сверки всей группы, даже при запросе инкрементального режима.
|
||
- Нормализуются пересекающиеся targets одного account/predicate; RPC windows
|
||
ограничены UTC-месяцем, с защитной секундой по краям и точным storage filter.
|
||
Двадцать одинаковых запросов присоединяются к одной попытке. Частичное
|
||
пересечение расширяет pending target только непокрытым остатком. Запрос,
|
||
соединяющий несколько активных групп, fenced supersedes их producers и
|
||
перезапускает объединённый staging новой попыткой; старые handles наблюдают
|
||
successor без запуска работы. Этот случай может повторно загрузить ранее
|
||
staged страницы и должен учитываться в итоговых измерениях.
|
||
- Coordinator подаёт одну страницу за turn и выбирает screen перед history;
|
||
сетевой RPC не удерживает reservation/publication lock. Retry policy остаётся
|
||
в TbankClient. После terminal failure нет автоматического повторения.
|
||
При новой runId следующий request очищает unfinished staging/cursor;
|
||
ранее опубликованные интервалы первичной загрузки сохраняются. Observation
|
||
и создание нового service не запускают импорт.
|
||
- Evidence: `node test/sqlite.cjs tbank-operations-sync.e2e-spec.ts
|
||
tbank-operations-persistence.e2e-spec.ts` — 12 + 4 passed. Sync suite включает
|
||
настоящий дочерний process и SIGKILL между страницами, перед publish и сразу
|
||
после publish; child использует текущую сборку из `npm run build` и только
|
||
SQLite штатного isolated runner. После kill наблюдение не вызывает RPC,
|
||
запрос запускает unfinished window с первой страницы; committed result
|
||
и terminal state переживают kill-after-publish.
|
||
- Проверены полный квартал двух accounts, failure второго месяца и сохранность
|
||
всех прежних rows/coverage/timestamps, последующий atomic commit, 20-way
|
||
coalescing, overlap remainder, bridge handles, page priority, known invalid
|
||
token и отказ чужому account до RPC. Backend `npm run verify` — 35 suites /
|
||
255 tests, lint, app/test typechecks и build passed.
|
||
- Completed остаётся 2/27: 1.3 пока не подтверждена на новом локальном HTTP
|
||
read path; 2.1–2.2 имеют проверенное operations execution ядро, но ещё не
|
||
подключены к экранным owners/public sync API. Общий discovery/shared-source
|
||
scheduling, source TTL/coverage planner 2.3, HTTP envelopes и frontend
|
||
остаются впереди. Это не итоговое доказательство 6.1, 6.2 или gate 7.2.
|
||
Бюджет 500 мс и полный RPC navigation trace пока не измерялись.
|
||
|
||
### Checkpoint — operations coverage/freshness planner, 2026-09-25
|
||
|
||
- Продолжена 2.3: pure planner разделяет availability, freshness и asOf;
|
||
полнота вычисляется по union интервалов, независимо от pagination. Account
|
||
coverage обслуживает instrument subset, обратное не допускается. Current
|
||
moving end сохраняет наблюдённый asOf и не создаёт RPC на новый хвост внутри
|
||
TTL; в 300 секунд назначается сверка текущего UTC-месяца. Исторические полные
|
||
интервалы автоматически не перечитываются, реальные holes не скрываются,
|
||
после смены месяца незавершённый хвост прошлого месяца остаётся missing.
|
||
- Operations sync service получил `readPlan`: читает durable coverage,
|
||
проверяет account membership, возвращает plan и при необходимости запускает
|
||
existing request-driven worker. Observe всегда read-only; force перечитывает
|
||
показанные targets. Автоматическая сверка не добавляет RPC для уже полных
|
||
прошлых месяцев. Верхняя граница новой попытки ограничена временем запроса:
|
||
будущее не публикуется как подтверждённое coverage.
|
||
- Verification: backend `npm run verify` — 35 suites / 261 tests passed.
|
||
Pure calendar/planner suite — 8 tests: 299/300 секунд, current moving end,
|
||
explicit end, реальные gaps, instrument predicate, rollover и force.
|
||
`node test/sqlite.cjs tbank-operations-sync.e2e-spec.ts
|
||
tbank-operations-persistence.e2e-spec.ts` — 14 + 4 passed на итоговой сборке;
|
||
сохранены SIGKILL/race/atomic-quarter проверки. Новые SQLite сценарии
|
||
подтверждают 0 RPC свежего readPlan и stale observe, RPC обычного stale
|
||
request/force и отсутствие будущего coverage.
|
||
- Completed по-прежнему 2/27: это operations-часть planner, а не весь 2.3.
|
||
Source TTL 60/86400, discovery и shared sources, screen dependency plans,
|
||
comparisons/backfill/unknown lower bound, локальные HTTP owners и API envelope
|
||
ещё не поставлены. Новые функции пока не вызываются существующими HTTP GET.
|
||
Frontend/docs не изменялись; OpenAPI artifact не изменён. Budget 500 мс и
|
||
полный navigation RPC trace пока не измерены; change не архивирован.
|
||
|
||
|
||
### Checkpoint — local accounts/portfolio HTTP, 2026-09-25
|
||
|
||
- Закрыта 1.3: локальный membership/access owner, атомарная замена и удаление
|
||
подключения, discovery только по запросу, coalescing и revision/attempt fence.
|
||
SQLite/HTTP evidence: `tbank-connection.e2e-spec.ts` (4 tests) и
|
||
`tbank-local-reads.e2e-spec.ts` (6 tests). Проверены unknown/empty/stale,
|
||
два пользователя, unsupported/removed membership (закрытый счёт отсутствует
|
||
в GetAccounts с ACCOUNT_STATUS_OPEN), failed replacement, invalid token,
|
||
late publication после replace/delete и сохранение retained account data.
|
||
- Accounts и portfolio HTTP теперь читают локальные snapshots и возвращают
|
||
envelope; missing snapshot даёт null, observe не запускает работу. Полный
|
||
portfolio сохраняется без временного предела при неудачном обновлении.
|
||
Warm GET не вызывает GetAccounts, decrypt или metadata RPC. Exact total
|
||
`21.100000002` сохраняется. Двадцать одновременных reads объединяют discovery;
|
||
abandoned attempt восстанавливается только следующим обычным запросом.
|
||
- Исправлена freshness составного metadata: худшее обязательное состояние и
|
||
самый ранний успешный timestamp источников. Пустой aggregate использует TTL
|
||
membership (300 секунд); непустой portfolio — TTL snapshot (60 секунд).
|
||
Unit regression проверяет разные TTL и неизменность source timestamps.
|
||
- Verification: `npm run verify` — 36 suites / 255 tests passed;
|
||
`npm run openapi:generate` выполнен; runtime OpenAPI parity — 1 passed;
|
||
SQLite operations persistence/sync — 4 + 14 passed на актуальной сборке,
|
||
включая SIGKILL/recovery и атомарный refresh полного квартала/all.
|
||
- Completed 3/27. 3.1 не закрыта: legacy consumers личных позиций ещё используют
|
||
прежний путь. 2.3 и остальные source owners/API endpoints остаются в работе.
|
||
Backend OpenAPI сгенерирован; передача frontend snapshot и адаптация consumer
|
||
остаются задачами 4.2–4.3. Frontend/docs на этом этапе не изменялись.
|
||
Финальный gate 7.2, полный durability/rollback и профиль 500 мс/RPC reduction
|
||
не подтверждены. Change не архивирован.
|
||
|
||
|
||
### Checkpoint — batch 2.1–2.3, 3.1–3.2, 2026-09-25
|
||
|
||
- Закрыты **2.1, 2.2, 2.3, 3.1, 3.2**; completed **8/27**, remaining **19**.
|
||
- **2.1:** staging проверяет исходные ID, курсоры и конфликтующие версии,
|
||
включая смену state. Reconciliation обновляет дату/сумму, удаляет исчезнувшие
|
||
и отменённые операции только в перечитанном account/interval/predicate.
|
||
Полный квартал/all публикуется атомарно; ошибка средней страницы/месяца
|
||
сохраняет прежние строки, суммы, coverage и время. SQLite persistence —
|
||
**5 passed**, включая отдельного читателя, reopen и instrument predicate.
|
||
- **2.2:** coalescing пересечений включает whole-account/instrument scope;
|
||
новый экранный интервал обгоняет pending history, после публикации экранной
|
||
части остаток получает background priority. Force показанного периода не
|
||
ждёт несвязанный backfill: внутри durable intent хранится отдельная atomic
|
||
publication group. Её результат сохраняется при последующей ошибке истории.
|
||
SQLite sync — **17 passed**: 20 одинаковых requests, overlaps/bridge,
|
||
stale attempt, priority, failure без retry loop и реальные SIGKILL между
|
||
страницами, до/после publish; recovery запускается только новым запросом.
|
||
TbankClient остаётся единственным владельцем RPC limiter/retries.
|
||
- **2.3:** screen dependency planner описывает membership/portfolio,
|
||
applied operations, selected/previous/yearAgo через существующий income
|
||
planner, shared metadata/catalog/quote/company/metrics/calendars/candles.
|
||
Force исключает архив; ordinary ledger request после экранных интервалов
|
||
ставит недостающее account history с низким приоритетом. Оконные RPC идут
|
||
последовательно, без предварительной массовой подачи в limiter.
|
||
Unknown opening использует явный requested floor 1970, сохраняет unknown
|
||
boundary и не объявляет полную историю. TTL policy проверена на 59/60,
|
||
299/300, 86399/86400 секундах; calendar tests покрывают Moscow/UTC,
|
||
февраль, смену месяца/года, moving end и missing tail. Proto не обещает
|
||
default-from/inclusivity: используются явные bounds, защитная секунда и
|
||
точный локальный [from,to), без нового допущения о нижней границе источника.
|
||
План shared зависимостей готов; их persistent owners/execution и candle
|
||
prefetch поставляются задачами 3.4–3.6, public screen dispatch — 4.1.
|
||
- **3.1:** старые RAM portfolio snapshots удалены; accounts, stock/bond
|
||
personal positions и upcoming-events используют общий persistent owner.
|
||
Отдельный upstream portfolio fetch событий удалён. Missing member скрывает
|
||
aggregate/position, не превращается в ноль; summary другого счёта остаётся
|
||
доступной. Проверены metadata fallback, source timestamp, indefinitely stale
|
||
portfolio, known access failure и reopen. Local reads — **7 passed**;
|
||
portfolio structure HTTP теперь использует настоящую SQLite — **4 passed**
|
||
(точные валюты, отрицательные остатки и неизвестные valuations).
|
||
- **3.2:** ledger/person-instrument history читают SQLite transaction со
|
||
стабильным порядком occurredAt/accountId/brokerOperationId. HMAC cursor
|
||
связан с user/connection, all membership, нормализованным filter/limit и
|
||
account row revisions, без connection identifier в payload. Изменение
|
||
coverage/time не ломает cursor; изменение rows/owner/connection — ломает.
|
||
Read-only observe не ставит work; partial coverage не становится complete
|
||
из-за hasNext=false, category/UID или размера страницы. HTTP SQLite —
|
||
**5 passed**, включая reopen, равные даты/ID, equivalent categories и
|
||
отсутствие RPC старых полных страниц. RAM page TTL read path удалён.
|
||
Legacy RPC collector сохранён только для ещё не переведённого income (3.3).
|
||
- **Gates:** `npm run verify` — **38 suites / 235 tests passed**, lint,
|
||
app/test typecheck и build успешны. `npm run openapi:generate` выполнен;
|
||
`openapi-contract.e2e-spec.ts` — **1 passed**. Дополнительно сохранены
|
||
connection SQLite/HTTP — **4 passed**. Всего relevant SQLite/HTTP —
|
||
**43 passed** (1 + 4 + 5 + 17 + 7 + 5 + 4), рабочая БД не использовалась.
|
||
`git diff --check` успешен; native validation и specs gate выполнены.
|
||
- Frontend/docs в этом batch не изменялись. Generated backend `openapi.json`
|
||
содержит новые envelopes; явная передача consumer snapshot остаётся 4.2.
|
||
Профиль 500 мс/RPC reduction, итоговый durability/rollback и gates 7.2–7.5
|
||
не закрыты; change не архивирован и не объявляется завершённым.
|
||
- **Следующий Implementation outcome:** 3.3 — income/summary из согласованного
|
||
локального набора операций с отдельной готовностью selected/previous/yearAgo
|
||
и сохранением прежнего полного результата при неудачной сверке.
|
||
|
||
|
||
### Checkpoint — local income/summary, 2026-09-25
|
||
|
||
- Закрыта **3.3**, completed **9/27**, remaining **18**. Income/summary читают
|
||
операции, coverage и membership одной SQLite read transaction. Удалён
|
||
последний synchronous operations collector; income больше не получает
|
||
cursor pages или metadata до HTTP-ответа.
|
||
- Selected, previous и yearAgo имеют отдельные coverage/status; неполный
|
||
selected возвращает data:null, незагруженное сравнение — null без нулевой
|
||
базы. Невозможное календарное/историческое сравнение имеет unavailableReason.
|
||
Moscow inclusive dates преобразуются в half-open UTC; historical period
|
||
не расширяется до now, current month сохраняет подтверждённый asOf.
|
||
Расчёты используют прежние decimal helpers и source timestamps.
|
||
- Наблюдённые проверки: `npm run verify` — **36 suites / 232 tests passed**,
|
||
lint, app/test typecheck и build; `npm run openapi:generate` выполнен.
|
||
`node test/sqlite.cjs tbank-income-local.e2e-spec.ts
|
||
tbank-ledger-local.e2e-spec.ts tbank-operations-persistence.e2e-spec.ts
|
||
tbank-operations-sync.e2e-spec.ts openapi-contract.e2e-spec.ts` —
|
||
**7 + 5 + 5 + 17 + 1 passed**. Только временные изолированные SQLite.
|
||
Income HTTP проверяет exact signed multi-currency sums, одинаковые ID разных
|
||
accounts, correction без повторного учёта, partial all/complete empty,
|
||
раздельные comparisons, другой period, source time/asOf, reopen, observe,
|
||
blocked upstream, access/period validation и невидимость unfinished staging
|
||
с сохранением старого финансового результата после failure.
|
||
- Старые mock-only suites синхронного collector заменены SQLite income
|
||
проверками; pure финансовые проверки сохранены. Backend OpenAPI содержит
|
||
income envelopes и nullable previous. Передача consumer snapshot остаётся
|
||
задачей 4.2; frontend/docs на этом этапе не изменялись.
|
||
- В запрошенном batch **3.4–3.6 и 4.1 ещё не выполнены**. Общие источники,
|
||
свечи, durable forecasts и public sync API требуют дальнейшей реализации.
|
||
Измерения профиля 500 мс/RPC reduction и финальные gates не закрыты.
|
||
Change не архивирован и implementation complete не заявлен.
|
||
- **Следующий Implementation outcome:** 3.4 — общие сохранённые catalog,
|
||
metadata, quotes, company/metrics с раздельной freshness и revision fence.
|
||
|
||
### Checkpoint — shared UID/FIGI metadata, 2026-09-25
|
||
|
||
- Продолжена **3.4**; checkbox остаётся открытым, completed **9/27**,
|
||
remaining **18**. Existing InstrumentMetadataService теперь использует
|
||
сохранённые Instrument/InstrumentLookup и private SyncWork вместо RAM TTL.
|
||
Успешное отсутствие отделено от failed lookup; UID/FIGI fallback и aliases
|
||
сохраняются, FIGI не превращается в выдуманный provider UID.
|
||
- Успешная metadata переиспользуется между пользователями и после reopen.
|
||
Для одинакового UID/FIGI descriptor requests объединяются в producer,
|
||
наблюдатели получают собственные handles. Publication и ошибки fenced
|
||
по текущей connection revision/attempt; удалённый/заменённый инициатор не
|
||
изменяет даже общий timestamp. Ошибка его credentials не становится общим
|
||
отрицательным lookup и не передаётся другому пользователю.
|
||
- Worker запускается только запросом, читает credentials только для актуальной
|
||
attempt и подаёт последовательные вызовы через прежний TbankClient.
|
||
Observe и создание нового service не восстанавливают unfinished intent;
|
||
новый обычный запрос меняет attempt. Нет startup scan, timer или retry loop.
|
||
Внутренний force обходит TTL, присоединяется к активной работе и сохраняет
|
||
ещё свежий источник/время при ошибке. Public screen sync остаётся в 4.1.
|
||
- Portfolio normalization и ledger читают metadata из SQLite. Обычные запросы
|
||
планируют отсутствующую/устаревшую metadata показанных позиций/операций;
|
||
observe этого не делает. Изменение metadata журнала меняет stateVersion,
|
||
сохраняя pagination binding и действующий cursor. Batch 1000 identities
|
||
проверен реально: обнаруженный SQLite/Prisma parameter limit устранён
|
||
ограниченными IN queries в одной read transaction.
|
||
- Evidence: `npm run verify` — **35 suites / 216 tests passed**, lint,
|
||
app/test typecheck и build. Старые RAM-only metadata mocks заменены реальной
|
||
SQLite suite. `node test/sqlite.cjs tbank-metadata-persistence.e2e-spec.ts
|
||
tbank-local-reads.e2e-spec.ts tbank-ledger-local.e2e-spec.ts
|
||
portfolio-structure.e2e-spec.ts tbank-income-local.e2e-spec.ts
|
||
openapi-contract.e2e-spec.ts` — **15 + 7 + 6 + 4 + 7 + 1 passed**.
|
||
Проверены 20-way coalescing, два пользователя, UID/FIGI/negative/sparse
|
||
outcomes, transient fallback, 86399/86400 seconds, failed force, late
|
||
completion после replace/delete, superseded attempt, reopen/request-only
|
||
recovery, сохранность финансовых read paths и runtime OpenAPI parity.
|
||
Использованы только временные изолированные SQLite; `git diff --check` passed.
|
||
- Не закрыты catalog discovery/enrichment, stock/bond company/metrics/quotes
|
||
и оставшиеся shared projections 3.4; candles 3.5, forecasts 3.6 и API 4.1
|
||
также впереди. Полный профиль 500 мс/RPC reduction не измерен; новые RPC
|
||
assertions относятся к указанным controlled-source tests. Frontend/docs
|
||
не изменены, consumer artifact не передавался, change не архивирован.
|
||
- **Следующий Implementation outcome:** продолжить 3.4 — persistent catalog
|
||
discovery с отдельными enrichment/quote sources и локальные stock/bond reads,
|
||
сохранив query identity, ticker ambiguity и MOEX/NCR semantics.
|
||
|
||
### Checkpoint — persistent catalog discovery owner, 2026-09-25
|
||
|
||
- Продолжена **3.4**, checkbox открыт: completed **9/27**, remaining **18**.
|
||
Добавлен concrete CatalogDiscoveryRepository/Service в instruments module.
|
||
Успешный discovery сохраняет упорядоченные UID по нормализованному query/type
|
||
отдельно от минимальных public catalog identities в InstrumentSource.
|
||
Отсутствующий query возвращает null; подтверждённый пустой — []. Сохранённый
|
||
SBER не подтверждает GAZP или bond query. Enrichment не требуется для чтения
|
||
найденных identities и не считается подтверждённым этим discovery.
|
||
- Existing stock/bond selection вынесен в один используемый обоими owners
|
||
helper: trade availability, exact ticker, preferred class, UID ordering,
|
||
ISIN dedup и отдельные missing-ISIN UID сохранены. Discovery сохраняет
|
||
прежний предел 30 после dedup. Минимальный catalog payload явно выбирает
|
||
public поля и не перезаписывает уже имеющуюся полную Instrument metadata
|
||
или её timestamp; InstrumentLookup completeness не создаётся автоматически.
|
||
- Read/request/observe API нового owner использует local access, durable private
|
||
work handles, дневной TTL и existing TbankClient. Одинаковые query/type двух
|
||
пользователей объединяются; credentials берутся только у актуального
|
||
producer. Shared writes и final states защищены connection/attempt fence.
|
||
Recovery запускается только обычным запросом; observe и создание service
|
||
работу не возобновляют. Failed force сохраняет прежний набор и timestamp.
|
||
- Evidence: backend `npm run verify` — **35 suites / 216 tests passed**,
|
||
lint, оба typecheck и build. `node test/sqlite.cjs
|
||
tbank-catalog-discovery.e2e-spec.ts tbank-metadata-persistence.e2e-spec.ts` —
|
||
**10 + 15 passed** на disposable SQLite со штатными migrations. Проверены
|
||
normalized/different queries/types, successful empty/unknown, reopen,
|
||
20-way coalescing, private handles, whitelist shared fields, независимость
|
||
полной metadata, late replace/delete, invalid-token isolation, superseded
|
||
attempt, request-only recovery, failed force и 86399/86400-second boundary.
|
||
- **Ограничение этапа:** новый discovery owner зарегистрирован в DI, но HTTP
|
||
search/detail ещё использует legacy orchestration. Его переключение вместе
|
||
с отдельными persistent enrichment/quote sources остаётся в 3.4; заявлять
|
||
локальный HTTP-поиск или отсутствие его broker wait пока нельзя. Company,
|
||
bond metrics/MOEX/NCR, candles, forecasts и public sync API также остаются.
|
||
Wire contract не менялся; frontend/docs и consumer snapshot не затронуты.
|
||
Профиль 500 мс/RPC navigation trace не измерялся; change не архивирован.
|
||
- Specs `npm run verify` и native strict validation `persist-tbank-data`
|
||
с явным `--store wealth-ledger-specs` успешны; backend/specs diff whitespace
|
||
checks успешны, включая новые source/test files.
|
||
|
||
|
||
### Checkpoint — local stock/bond search and persistent enrichment, 2026-09-25
|
||
|
||
- Продолжена **3.4**, completed **9/27**, remaining **18**. HTTP GET `/stocks`
|
||
и `/bonds` теперь читают сохранённые discovery/detail/last-price sources,
|
||
возвращают `{data, meta}` и поддерживают `sync=observe`. Неизвестный query
|
||
даёт null, подтверждённый пустой — []; найденные identities доступны при
|
||
незавершённых/отказавших enrichment sources. Метаданные описывают отдельные
|
||
зависимости, их availability/freshness/private work handles; resourceKey
|
||
стабилен между missing и последующим результатом.
|
||
- CatalogEnrichmentService сохраняет типизированные детали по UID и prices
|
||
раздельно. TTL деталей — сутки, prices — минута; повторный query использует
|
||
уже сохранённые sources независимо от пользователя. Cold discovery запускает
|
||
запрошенные enrichment dependencies самостоятельно, поэтому observe не обязан
|
||
инициировать следующий этап. UID работ объединяются между query/users;
|
||
до 30 цен одного producer идут одним existing getLastPrices RPC, подробности
|
||
запрашиваются последовательно через existing TbankClient. Новых dependencies,
|
||
migration, scheduler или внешней очереди нет.
|
||
- Публикация каждого source проверяет current connection/revision/attempt;
|
||
batch дополнительно проверяет initiating attempt. Удаление/замена подключения
|
||
или superseded initiating attempt не позволяют опубликовать остальные цены
|
||
batch. Failed force оставляет прежние данные и timestamps. Shared payload
|
||
явно выбирает public fields. Успешные полезные детали также обновляют canonical
|
||
Instrument и UID/FIGI aliases внутри той же transaction: generic metadata
|
||
owner переиспользует результат без повторного RPC. Successful typed miss
|
||
не становится отрицательным generic UID lookup.
|
||
- Сохранены decimal price mapping, bond pricePercent отдельно от Money,
|
||
nominal/ACI, UID matching пакетных цен, selection/dedup/limit. Legacy mock
|
||
tests синхронного search заменены реальными SQLite/HTTP сценариями; прежние
|
||
ticker/market/company финансовые tests продолжают проходить.
|
||
- Evidence на итоговом коде: backend `npm run verify` — **35 suites / 209 tests**,
|
||
lint, оба typecheck и build passed. `npm run openapi:generate` выполнен.
|
||
`node test/sqlite.cjs tbank-catalog-local.e2e-spec.ts
|
||
tbank-catalog-discovery.e2e-spec.ts tbank-metadata-persistence.e2e-spec.ts
|
||
tbank-ledger-local.e2e-spec.ts stocks.e2e-spec.ts bonds.e2e-spec.ts
|
||
openapi-contract.e2e-spec.ts` — **15 + 10 + 15 + 6 + 16 + 18 + 1 = 81 passed**.
|
||
HTTP sandbox EPERM повторён с разрешённым локальным loopback; итоговый прогон
|
||
успешен. Только disposable SQLite, рабочая БД не использовалась.
|
||
- Проверены blocked discovery/enrichment без ожидания HTTP, partial/empty/unknown,
|
||
shared reuse после reopen без decrypt/GetAccounts/RPC, одна price batch на
|
||
30 бумаг, межпользовательские/private handles, failed force, независимые minute/
|
||
day TTL, wrong detail UID, late replace/delete и superseded batch origin,
|
||
request-only recovery, финансовые строковые значения и configured access/DTO
|
||
validation. Эти RPC assertions не заменяют полный профиль измерений 6.2:
|
||
500 мс и navigation RPC reduction пока не подтверждены.
|
||
- **Остаток 3.4:** локальные UID/ticker detail endpoints, company/fundamentals,
|
||
полноценные quote/metrics owners и MOEX/NCR semantics; legacy synchronous
|
||
read paths этих sections пока сохранены. Candles/forecasts/public sync API
|
||
остаются 3.5/3.6/4.1. Backend OpenAPI обновлён, явная передача consumer snapshot
|
||
остаётся 4.2; frontend/docs в этом этапе не менялись. Change не архивирован,
|
||
задача 3.4 и общий implementation complete не объявлены.
|
||
|
||
|
||
### Checkpoint — local instrument sections, 2026-09-25
|
||
|
||
- Завершена **3.4**, completed **10/27**, remaining **17**. UID/ticker,
|
||
company/fundamentals, quotes и bond metrics читают SQLite и поддерживают
|
||
observe; missing не превращается в пустой финансовый результат. Exact ticker
|
||
проверяется до listing selection/ISIN dedup; неоднозначность сохраняется,
|
||
optional alias не подменяет запрошенный UID другой площадкой.
|
||
- Details/company/ratings и minute quote sources сохраняются раздельно.
|
||
MOEX yield и NCR rating сохраняют source identity, точные значения и прежние
|
||
timestamps при failed force. Shared sources не содержат private projections;
|
||
два пользователя используют общий результат с private handles. Сохранённая
|
||
metadata обновляет названия/логотипы portfolio без изменения финансовых сумм
|
||
и времени portfolio snapshot.
|
||
- Исправлена гонка присоединения наблюдателя во время SQLite publication:
|
||
producer остаётся зарегистрированным до обработки всех присоединений.
|
||
Реальный DB test доказывает один RPC и два завершённых private handles.
|
||
- Evidence: `npm run verify` — **35 suites / 196 unit tests**, lint, app/test
|
||
typecheck, build passed; `npm run openapi:generate` passed. SQLite/HTTP suites
|
||
catalog-local/discovery/metadata/local-reads/portfolio/ledger/stocks/bonds/
|
||
openapi-contract: **22+10+15+7+4+6+16+18+1 passed**; после финальных additions
|
||
local-reads **8 passed**, catalog-local **24 passed**. Runtime OpenAPI parity
|
||
passed; HTTP fixtures используют постоянный loopback listener. Только
|
||
disposable SQLite и synthetic credentials; `git diff --check` passed.
|
||
- Tasks **3.5, 3.6, 4.1, 4.2** запрошенного batch ещё не завершены. Свечи,
|
||
payouts/events пока сохраняют legacy orchestration. Передача OpenAPI consumer
|
||
snapshot ещё не выполнена; frontend/docs не изменены. Полный профиль latency/
|
||
RPC 6.2 не измерен; implementation complete и archive не заявлены.
|
||
- **Следующий Implementation outcome:** 3.5 — durable candle coverage с
|
||
source-confirmed closed ranges, mutable tail и request-only recovery.
|
||
|
||
|
||
### Checkpoint — persistent candle reads and atomic reconciliation, 2026-09-25
|
||
|
||
- Продолжена **3.5**, checkbox открыт; completed **10/27**, remaining **17**.
|
||
Stock/bond candles HTTP теперь возвращает локальный `{data, meta}` с observe.
|
||
Durable CandleRepository использует существующие Candle/Coverage/SyncWork/
|
||
SyncStage; новых schema, dependencies, scheduler или startup scan нет.
|
||
- Диапазоны до 365 суток собираются в staging и публикуются общей transaction.
|
||
Повторная сверка удаляет исчезнувшие свечи только своего диапазона, сохраняет
|
||
coverage вне него и при ошибке следующего окна оставляет предыдущие данные
|
||
и timestamps целиком. Late/superseded/deleted attempts не публикуют данные.
|
||
- Closed empty coverage переиспользуется после reopen; source isComplete и
|
||
точные decimal strings сохраняются, bond close остаётся процентом. Текущий
|
||
UTC-день, включая пустой, изменяемый с minute TTL; смена дня сама не закрывает
|
||
старое empty/incomplete окно. Полнота ответа отделена от TTL: истечение минуты
|
||
сохраняет полный результат с stale freshness. Unknown historyFrom для all
|
||
сохраняет STOCK/BOND_HISTORY_START_UNAVAILABLE.
|
||
- 20 одновременных запросов объединяются, typed metadata ожидается только внутри
|
||
worker через существующего source owner. Observe не возобновляет abandoned
|
||
intent; следующий обычный запрос меняет attempt и запускает работу. Worker
|
||
последовательно подаёт RPC через existing TbankClient.
|
||
- Evidence итогового кода: `npm run verify` — **36 suites / 197 unit tests**,
|
||
lint, оба typecheck и build passed; дополнительный `npm run typecheck:test`
|
||
после последнего SQLite scenario passed. OpenAPI generated; последовательный
|
||
runtime parity passed. `node test/sqlite.cjs
|
||
tbank-candles-persistence.e2e-spec.ts tbank-catalog-local.e2e-spec.ts
|
||
tbank-local-reads.e2e-spec.ts stocks.e2e-spec.ts bonds.e2e-spec.ts
|
||
openapi-contract.e2e-spec.ts` — **8+26+8+16+18+1 = 77 passed**.
|
||
Первый parity run пересёкся с build и увидел прежний dist; итоговый прогон
|
||
выполнен после завершения build/generation. Только disposable SQLite;
|
||
`git diff --check` passed.
|
||
- **Остаток 3.5:** portfolio-only prefetch через screen planner, продолжение
|
||
дальней истории после показанного периода и интеграция quote comparison
|
||
с общей candle coverage. Нужна итоговая проверка очередности/предзагрузки
|
||
и полного crash/restart поведения после этой интеграции. Поэтому 3.5 не
|
||
отмечена выполненной. Tasks **3.6, 4.1, 4.2** также не завершены; весь batch
|
||
из пяти задач не выполнен. Frontend/docs и consumer snapshot не изменялись.
|
||
Профиль p95 500 мс/RPC reduction не измерялся; archive не выполнялся.
|
||
- **Следующий Implementation outcome:** завершить 3.5 — подключить planner
|
||
предзагрузки только сохранённых portfolio instruments к тому же candle owner
|
||
без циклических DI dependencies и подтвердить remaining Verification.
|
||
|
||
|
||
### Checkpoint — portfolio candle prefetch and screen priority, 2026-09-25
|
||
|
||
- Завершена **3.5**, completed **11/27**, remaining **16**. Existing shared
|
||
instrument providers собраны в InstrumentSourcesModule без дублирования DI
|
||
instances и forwardRef; PortfolioModule использует публичный CandleService.
|
||
- Предзагрузка отбирает только сохранённые STOCK/BOND positions с UID, удаляет
|
||
дубликаты и применяет existing screen planner. На warm portfolio read её DB
|
||
планирование не блокирует HTTP; одинаковые активные prefetch объединяются.
|
||
Открытый не входящий в portfolio инструмент получает собственную историю.
|
||
- После показанного периода очередь продолжает all-history с меньшим
|
||
приоритетом. Каждый RPC-window уступает место экранным dependencies;
|
||
automatic windows публикуются постепенно, force остаётся атомарным для
|
||
всего показанного периода. Coverage повторно проверяется между окнами.
|
||
Quote comparison сохраняет и переиспользует тот же durable candle coverage.
|
||
- Evidence: backend `npm run verify` — **36 suites / 197 tests**, lint, оба
|
||
typecheck, build passed. OpenAPI generated. SQLite candles/catalog/local reads/
|
||
portfolio/OpenAPI suites — **9+26+8+4+1 = 48 passed**, включая ordering между
|
||
окнами, portfolio-only scope, opening another instrument, request-only recovery,
|
||
midnight/empty coverage, failed force, exact bond percentage и comparison reuse.
|
||
Использована только disposable SQLite; latency/RPC profile 6.2 не измерялся.
|
||
- **Следующий Implementation outcome:** 3.6 — shared payout calendars и private
|
||
last-complete forecast fallback с исходными timestamps и membership/range fence.
|
||
|
||
|
||
### Checkpoint — durable payout calendars and forecasts, 2026-09-25
|
||
|
||
- Завершена **3.6**, completed **12/27**, remaining **15**. Instrument dividends,
|
||
coupons и account/all events читают saved calendars + persistent portfolio,
|
||
возвращают envelope и поддерживают observe. Stock/bond legacy RAM callbacks
|
||
и отдельные synchronous calendar/portfolio fetch удалены. Общие источники
|
||
сохраняют raw events без quantities/estimates; account bond events остаются
|
||
MOEX, instrument coupons — T-Bank; missing MOEX block не становится [].
|
||
- ForecastService/Repository принадлежат existing private portfolio owner и
|
||
используют TbankForecast. Publication проверяет current connection/membership,
|
||
portfolio versions и shared source versions/timestamps в SQLite transaction.
|
||
Старый полный snapshot сохраняется при missing новой зависимости, ошибке
|
||
календаря и reopen; другой applied range/membership не получает его данные.
|
||
Successful одинаковые dependencies не меняют calculatedAt/исходные timestamps.
|
||
Public payout rows при missing personal snapshot не получают неподтверждённые
|
||
estimates; private calculations не возвращаются мимо publication fence.
|
||
- Сохранены exact signed/fractional money, валюты, registry dates, cancelled
|
||
dividends, offer без суммы, redemption отдельно от income totals, future
|
||
unfixed payout entitlement и optional metadata fallback к portfolio ticker.
|
||
- Evidence: `npm run verify` — **36 suites / 188 unit tests**, lint, оба
|
||
typecheck, build passed; старые synchronous-cache orchestration tests заменены
|
||
SQLite tests, pure financial checks сохранены. OpenAPI generated. SQLite/HTTP
|
||
upcoming-events/catalog/candles/local reads/stocks/bonds/OpenAPI —
|
||
**15+26+9+8+16+18+1 = 93 passed**, включая реальную optimistic-publication race,
|
||
two-user reuse/private values, new holding failure + reopen, membership/range
|
||
isolation, cancelled/empty/unknown calendars, MOEX failure, late connection
|
||
deletion, default/inclusive dates и observer without RPC. Только disposable DB.
|
||
- Consumer snapshot ещё не передан; frontend/docs не изменены. Профиль 500 мс/
|
||
RPC reduction остаётся 6.2, archive не выполнялся.
|
||
- **Следующий Implementation outcome:** 4.1 — validated screen-scoped force
|
||
dispatch и observational authorized status с DTO/OpenAPI и resource states.
|
||
|
||
### Checkpoint — sync contract preparation, 2026-09-25
|
||
|
||
- Запрошенная пятёрка **3.5, 3.6, 4.1, 4.2, 4.3**: первые две завершены;
|
||
**4.1 остаётся открытой**, общий счёт **12/27**. Добавлены DTO и подготовка
|
||
durable screen intent, нормализация разрешённых screen fields и scope;
|
||
это пока не подключённые публичные POST/status endpoints.
|
||
- Dependency DTO теперь описывает фактически возвращаемые dataRevision и
|
||
stateVersion. Общий mapper учитывает running/queued/failed dependencies,
|
||
сохраняя availability и successful timestamps прежнего результата.
|
||
Candle meta явно возвращает requested/complete/missing coverage независимо
|
||
от freshness; stale current tail не превращается в missing interval.
|
||
- Проверки: backend `npm run verify` — **37 suites / 192 tests passed**,
|
||
lint, оба typecheck и build; `npm run openapi:generate` passed.
|
||
`node test/sqlite.cjs tbank-candles-persistence.e2e-spec.ts
|
||
tbank-catalog-local.e2e-spec.ts tbank-local-reads.e2e-spec.ts
|
||
upcoming-events.e2e-spec.ts openapi-contract.e2e-spec.ts` —
|
||
**9+26+8+15+1 = 59 passed**. Только disposable SQLite и synthetic credentials.
|
||
Исправлена устаревшая неполная metadata fixture candle-тестов; unit income
|
||
изолирует Prisma import после расширения operations public provider exports.
|
||
- Frontend snapshot не передан, frontend не изменён; existing docs edits
|
||
сохранены. Полный профиль 500 мс/RPC 6.2 не измерялся; archive не выполнялся.
|
||
- **Следующий Implementation outcome:** завершить 4.1: подключить scoped
|
||
dispatcher к existing owners и observational status с текущими resource
|
||
stateVersion, проверить configured HTTP authorization/validation/observe
|
||
и coalescing на SQLite. Затем последовательно выполнить 4.2 и 4.3.
|
||
|
||
|
||
### Checkpoint — public sync/status and explicit OpenAPI handoff, 2026-09-25
|
||
|
||
- Завершены **4.1–4.2**, итог **14/27**. POST tbank-sync строго валидирует
|
||
screen scope, нормализует поля, резервирует private handle и возвращает 202
|
||
до broker completion. Concrete coordinator раскрывает dependency graph
|
||
через existing membership/portfolio/operations/catalog/calendar/candle owners.
|
||
Force не запускает full-history prefetch и сохраняет атомарность показанного
|
||
периода operations. Новая инфраструктура/dependencies не добавлены.
|
||
- Status авторизует current connection/account, использует только observe reads,
|
||
возвращает текущие resource stateVersion и terminal outcome. Поддержаны handles
|
||
обычных GET; abandoned work не запускается. Screen progress фиксирует child
|
||
attempts, superseded результат не приписывается прежнему запросу.
|
||
- Evidence: backend `npm run verify` — **37 suites / 192 tests**, lint, app/test
|
||
typecheck и build passed. SQLite/HTTP run screen-sync/all/local-reads/ledger/
|
||
income/catalog/candles/events/stocks/bonds — **10+18+8+6+7+26+9+15+16+18**.
|
||
Финальный screen-sync — **11 passed**, включая empty coverage stateVersion
|
||
без изменения dataRevision; runtime OpenAPI parity — **1 passed**.
|
||
20-way POST coalescing, 202 при заблокированном upstream, malformed/foreign
|
||
scope, private handles, failure без retry, old-process cancellation и
|
||
old-connection 404 проверены на disposable SQLite. All route tests обновлены
|
||
с legacy synchronous mock на настоящую локальную DB boundary.
|
||
- Backend `openapi.json` явно скопирован в frontend
|
||
`src/shared/api/spec/openapi.json`; frontend `npm ci`, локальные
|
||
`openapi:generate` и `openapi:check` успешны. Frontend CI не читает backend.
|
||
**4.3 остаётся открытой** до итоговых frontend lifecycle tests/gates.
|
||
- Профиль latency/RPC 6.2 не измерялся; archive не выполнялся. Следующий
|
||
Implementation outcome: завершить entity query envelope/observe owners и
|
||
доказать session/connection/access/latest-response fences во frontend.
|
||
|
||
|
||
### Checkpoint — frontend resource owners and response fences, 2026-09-25
|
||
|
||
- Завершена **4.3**, итог **15/27**, remaining **12**. Все investment entity
|
||
query owners используют backend envelope. Canonical generated query identity
|
||
хранит envelope, owners возвращают payload и meta существующим consumers.
|
||
Missing null не становится []/нулевым финансовым успехом. Types derived from
|
||
snapshot, включая nullable periods, проходят проверку всех consumers; account
|
||
VM использует accounts owner вместо прежнего raw-array cache cast.
|
||
- Observe использует тот же generated key с отдельным transport mode.
|
||
При несовпадении ожидаемого stateVersion stale response не публикуется;
|
||
повторяется только observational read. Transport объединяет identity ordinary/
|
||
observe для latest-request fencing. In-flight records с ограниченным временем жизни очищаются после
|
||
завершения; новая инфраструктура или зависимости не добавлены.
|
||
- Успешная connection mutation отменяет publication прежних data/status/mutation
|
||
responses и сбрасывает финансовые GET caches, включая sync status. Failed
|
||
mutation сохраняет caches/boundary. Session generation и unmount защищают
|
||
ответы от прежней session. Confirmed private access loss очищает snapshots,
|
||
отменяет связанные запросы и повышает access epoch; поздний success не
|
||
восстанавливает скрытые данные. Обычный 503 сохраняет cached snapshot.
|
||
- Sync mutation/status hooks готовы в existing tbank-connection feature;
|
||
автоматический page observer и действия refresh остаются **5.1**, не включены
|
||
в эти hooks. Existing frontend fixtures обновлены до нового wire envelope;
|
||
generic transport tests проверяют envelope, presentation tests — payload.
|
||
- Evidence: frontend `npm ci`, `openapi:generate`, `openapi:check`; полный
|
||
`npm run verify` успешен: typecheck, Biome, **51 suites / 287 tests** с coverage,
|
||
Knip, dependency/FSD и Storybook dependency gates, production build и
|
||
Storybook build. После усиления status-publication assertions targeted
|
||
sync tests **2 passed**, финальный typecheck passed. Полный gate ранее также
|
||
прошёл на итоговом production code. MSW/RTL проверяют canonical observe cache,
|
||
rejection старой версии, late ordinary/observe ordering, missing/failed null,
|
||
access loss + late sibling response, connection/session status и mutation.
|
||
Subscription на query cache подтверждает отсутствие публикации old status.
|
||
- Backend финальный `npm run verify` — **192 tests**, lint/type/build;
|
||
итоговые screen-sync **11 passed** и runtime OpenAPI parity **1 passed**.
|
||
Nested descriptor errors содержат field pointers. Backend artifact и явно
|
||
переданный frontend snapshot побайтово совпадают (`cmp`). Все DB проверки
|
||
использовали disposable SQLite. Diff whitespace checks успешны.
|
||
- Docs и root не менялись этим batch; прежние docs edits сохранены. Frontend
|
||
production/Storybook builds сообщают предупреждения о крупных chunks;
|
||
gates завершаются успешно. Browser proof/новые UI states остаются **6.3**,
|
||
latency/RPC profile **6.2** не измерялся. Archive не выполнялся.
|
||
- **Следующий Implementation outcome:** 5.1 — page-owned descriptor и passive
|
||
observer известной работы по inline UI/UX revision 1, с отдельными transport
|
||
и source lifecycle, остановкой observation после ухода или terminal outcome.
|
||
|
||
|
||
### Checkpoint — scoped screen refresh and populated rollback proof, 2026-09-25
|
||
|
||
- Завершены **5.1–5.4 и 6.1**, итог **20/27**, remaining **7**. Descriptors
|
||
принадлежат page VMs; existing tbank-connection feature наблюдает только
|
||
полученные handles. Status polling и canonical observe reads не инициируют
|
||
новые imports; terminal/leave/logout останавливают polling. Dependency-only
|
||
completion также перечитывает projection. Повторный POST текущего scope
|
||
защищён; поздний acceptance другого scope не заменяет текущий handle.
|
||
- Entity owner отдельно отдаёт transport status/error, сохраняя source metadata.
|
||
Known access failures очищают private snapshots с существующим epoch fence;
|
||
NOT_FOUND самого work handle не трактуется как потеря доступа ко всем счетам.
|
||
Transient transport failure и failed source work показываются раздельно;
|
||
прежние суммы, source timestamps и fresh до TTL сохраняются.
|
||
- Accounts различает unknown и complete-empty; карточки показывают timestamps
|
||
и freshness отдельных portfolio summaries. Account/all refresh охватывает
|
||
membership, portfolio, operations, income и events. Частичный portfolio
|
||
не показывает окончательные totals/structure; подтверждённые позиции и
|
||
operations/events остаются видимыми с сообщением о неполноте. Overview
|
||
sections сохраняют независимые partial/error/stale состояния.
|
||
- Operations/income/events используют applied scope и source completeness.
|
||
Partial empty не получает финансовый empty message; selected income не
|
||
ждёт year comparison и не получает вымышленную нулевую базу. Cursor recovery
|
||
возвращает первую страницу с прежними dates/categories. Смена периода не
|
||
переименовывает прежний snapshot; сохранённый forecast виден с исходным
|
||
временем при failed source refresh.
|
||
- Stock/bond search и detail используют те же source states. Ручной refresh
|
||
передаёт текущие UID, candle period и personal-history categories/limit,
|
||
не сбрасывает график и не запрашивает весь каталог. Общий section adapter
|
||
учитывает missing/partial/stale/failed и source timestamps; незавершённые
|
||
свечи и неподтверждённые personal estimates не превращаются в нули.
|
||
- Frontend evidence: итоговый `npm run verify` — **53 suites / 306 tests**,
|
||
OpenAPI check, typecheck, Biome, coverage, Knip, FSD/dependency и Storybook
|
||
dependency checks, production и Storybook builds passed. MSW/RTL проверяют
|
||
duplicate POST, terminal/leave/logout, переход времени за TTL без ordinary
|
||
GET, empty completion при ещё running history, dependency completion,
|
||
access loss, fresh snapshot при failed force, scope stock/bond, independent
|
||
overview/summary freshness, полный overview observe и invalid cursor recovery.
|
||
Ранее созданные race/negative-correction/period-boundary проверки также
|
||
входят в этот итоговый gate. Browser/reduced-motion/viewport proof остаётся
|
||
**6.3**, успешная Storybook build его не заменяет.
|
||
- Backend evidence: `npm run verify` — **37 suites / 192 tests**, lint, оба
|
||
typecheck и build passed. Исправлены unsafe Jest asymmetric matcher values
|
||
в screen-sync test, runtime assertions field pointers сохранены. Через
|
||
`node test/sqlite.cjs` прошли operations-sync/migration/connection/catalog/
|
||
candles/events — **17+2+4+26+9+15**, затем operations-persistence/ledger-local/
|
||
screen-sync — **5+6+11**; всего **95 SQLite/HTTP checks**. Включены SIGKILL
|
||
между страницами и до/после publish, отдельный concurrent SQLite reader,
|
||
reopen/request-only recovery, membership replace/delete и shared fences.
|
||
- Existing `test/bank-cards-durability.cjs` расширен populated T-Bank datasets,
|
||
coverage, forecasts, shared sources, staging/progress и migration state.
|
||
`npm run test:durability -- /tmp/wealthledger-tbank-rollback.PuzfjF` passed:
|
||
equality после restart, rollback/return и restore в другую SQLite; integrity
|
||
и FK checks; User/Session/connection/manual cards, refunds/tombstones и новые
|
||
datasets сохранены. Evidence result:
|
||
`/var/folders/j_/h2ft23gd3qq35ps3v5bcftfm0000gn/T/wealthledger-bank-durability-7MLwhL/result.json`.
|
||
- Rollback pair проверена явно: JSON OpenAPI, сгенерированный прежним backend
|
||
**0862d56c4e4d9dd554556c3992cc073193020ff1**, равен consumer snapshot frontend
|
||
**a209d715892862bb6d48084df0c84a10b8d56bf1** (`db184c8^`). Более новый
|
||
frontend HEAD содержит другой validation/conflict contract и не объявлен
|
||
подходящей парой этого rollback build. Deploy/rollback реального приложения
|
||
не выполнялись. Текущие backend OpenAPI и явно переданный frontend snapshot
|
||
побайтово совпадают (`cmp`); новых public DTO изменений в этом batch нет.
|
||
- Только disposable SQLite/synthetic credentials; рабочая БД не использовалась.
|
||
Root/docs не менялись, прежние docs edits сохранены. `git diff --check` passed.
|
||
Builds сохраняют предупреждения о крупных chunks. Профиль **500 мс/RPC
|
||
reduction 6.2 ещё не измерен**; implementation complete не объявлена.
|
||
Remaining: **6.2, 6.3, 7.1–7.5**. Archive/main-spec sync не выполнялись.
|
||
- **Следующий Implementation outcome:** 6.2 — измерить HTTP/RPC по согласованному
|
||
профилю и baseline trace; затем 6.3 — browser verification inline UI revision 1.
|
||
|
||
|
||
### Checkpoint — measured reads, browser proof and application gates, 2026-09-25
|
||
|
||
- Завершены **6.2, 6.3, 7.1, 7.2, 7.3**, итог **25/27**, remaining **2**.
|
||
Backend сохраняет existing owners: batch reads coverage/source work заменяют
|
||
загрузку свечей и N+1 queries при prefetch/projection; Intl formatter reused.
|
||
Проверка source versions прогноза разбита на batches внутри одной transaction,
|
||
чтобы 200 инструментов не превышали SQLite parameter limit. Financial
|
||
publication fences и fallback сохранены; новой инфраструктуры нет.
|
||
- Performance runner: `node test/sqlite.cjs tbank-read-baseline.e2e-spec.ts`.
|
||
Evidence: backend `test/fixtures/tbank-read-persistent.json`. Изолированный
|
||
Docker, network none, без volumes; cgroup 4 CPU / 8 GiB (VM доступно 7.65 GiB),
|
||
Apple M1 Pro SSD host, Node 24.21.0. SQLite 619343872 bytes: 300000 операций,
|
||
1000000 свечей, 3 счёта / 200 инструментов. Dependency entries image lock
|
||
совпадают с текущим lock; отличается только version корневого package.
|
||
- **2300 warmed reads: 23 группы × 100, concurrency 10**. Server ingress →
|
||
response finish p95 **7.3–382.6 ms**, все группы ≤500 ms. p50/p99/max/bytes
|
||
сохранены. Первый DB-only read после Nest/provider restart: **71.2 ms client**
|
||
(HTTP logger 16 ms). Это не OS-process restart; отдельный process crash/reopen
|
||
проверен durability suite. Fresh mutable timestamps обновлялись перед каждой
|
||
группой, чтобы измерять именно fresh path; полный прошлый coverage сохранён.
|
||
- Baseline navigation trace: **42913 → 0** synthetic TbankClient calls (100%
|
||
reduction), включая первые reads; baseline repeated-only часть — 41821.
|
||
Реальный внешний broker network не измерялся; baseline host latency не
|
||
сравнивается с container latency. 20 stale requests: один portfolio и один
|
||
positions pass, retries 0; все ответы за 1717 ms при upstream delay 2000 ms.
|
||
Cold import ответ 18.3 ms; завершённая работа без новых запросов RPC не делает.
|
||
**Client p95 достигает 3556.4 ms**: server budget не означает end-to-end
|
||
browser latency ≤500 ms; client timings сохранены отдельно.
|
||
- Frontend: existing stories independent summary freshness/source failure;
|
||
фоновые warnings используют polite status announcements. Chrome/Playwright
|
||
**56 app checks**, **9 Storybook viewport checks**: 320/375/1440, длинные суммы,
|
||
account/all, ledger, income, events, stock/bond, complete/partial/stale/failed/
|
||
missing, refresh, leave/reopen, connection replacement, keyboard/focus,
|
||
skeleton/busy и reduced motion; JS errors 0. Synthetic API fixtures, без
|
||
реальных credentials. Проверка resize ждёт завершения responsive chart layout;
|
||
первоначальный transient overflow воспроизводился до перерасчёта, после него
|
||
отсутствует. CSS workaround не добавлялся. Evidence текущего запуска:
|
||
`/tmp/wealthledger-browser-evidence.json`, `/tmp/wealthledger-ui-final3.log`,
|
||
`/tmp/wealthledger-stories-check.log`, screenshots `/tmp/wl-*.png`.
|
||
- Backend: `npm ci`, `npm run verify` (**37 suites / 192 tests**),
|
||
`npm run test:openapi-contract`, `npm run openapi:generate` passed.
|
||
SQLite/HTTP candles/catalog/discovery/events/income/local reads/screen-sync:
|
||
**86 checks passed**; durability/rollback повторно passed на disposable DB,
|
||
result `wealthledger-bank-durability-kWQOEX`. Рабочая БД не использовалась.
|
||
Финальный backend OpenAPI побайтово равен явно переданному frontend snapshot.
|
||
- Frontend: `npm ci`, `npm run verify` (**53 suites / 306 tests**), включая
|
||
local OpenAPI drift, type/lint/coverage/Knip/dependencies, production и
|
||
Storybook builds passed. Крупные chunks остаются build warnings.
|
||
- Docs обновляет storage/access/freshness, flows accounts/operations/portfolio/
|
||
income/instruments, HTTP handoff и glossary; ADR 017 сохраняет историческое
|
||
решение и отмечает проверенную реализацию в рабочих ветках, не production
|
||
deployment. README routes к темам/терминам/API сохранены. Полный отдельный
|
||
semantic/diagram gate **7.4 остаётся открытым**.
|
||
- Specs `npm ci` успешно повторён без изменения dependencies после прежнего
|
||
registry 502. Diff/owner/callers review выполнен; чужие active changes и
|
||
staged/unstaged изменения сохранены. Итоговая requirement-by-requirement
|
||
сверка **7.5 остаётся открытой**. Реализация целиком завершённой не объявляется;
|
||
archive/main-spec sync и deployment не выполнялись.
|
||
- Финальные `npm run verify` docs (**46 Markdown files, 0 issues**) и specs
|
||
passed; strict native validation change с explicit store passed. Native apply
|
||
подтверждает **25 completed / 2 remaining**. Эти проверки не заменяют 7.4/7.5.
|
||
- **Следующий Implementation outcome:** 7.4 — финальная semantic/link/diagram
|
||
проверка docs, затем 7.5 — все 35 delta requirements и native final gates.
|
||
|
||
|
||
### Checkpoint — final semantic and requirement verification, 2026-09-26
|
||
|
||
- Завершены **7.4–7.5**, итог **27/27 implementation-owned tasks**.
|
||
Сверены все **35 delta requirement headings**, включая REMOVED; таблица ниже
|
||
связывает каждый heading с задачами и наблюдаемыми проверками.
|
||
- Semantic review обнаружил и устранил пропуски frontend: список счетов и его
|
||
skeleton теперь одноколоночные согласно delta requirement; аналитика показывает
|
||
previous comparison через существующий компонент отдельно от yearAgo. Для
|
||
каждого сравнения различаются incomplete, source failure и недоступность
|
||
годового сравнения по календарю/истории; null не становится нулевой базой.
|
||
Financial Money приходит с сервера, новые calculations/API поля не добавлялись.
|
||
- Frontend `npm ci`, targeted income (**41 tests**) и `npm run verify`
|
||
(**53 suites / 307 tests**) passed: local OpenAPI drift, type/lint/coverage,
|
||
Knip/dependency checks, production и Storybook builds. Финальный browser run:
|
||
**56 app cases**, **9 Storybook viewport checks**, затем **14 focused income
|
||
checks**, включая видимость обоих сравнений на 320/375/1440 px; JS errors 0.
|
||
Storybook проверяет расположение второй account card ниже первой на каждой
|
||
ширине. Evidence: `/tmp/wealthledger-frontend-verify27.log`,
|
||
`/tmp/wealthledger-ui27.log`, `/tmp/wealthledger-stories27.log`,
|
||
`/tmp/wealthledger-income-browser27.log`, screenshots `/tmp/wl-previous-*.png`.
|
||
- Docs: пройдены маршруты README → architecture/flows → glossary/HTTP API.
|
||
Убраны оставшиеся утверждения о временном portfolio, потере snapshots после
|
||
restart, отсутствии force action и совместимости старого клиента с envelope.
|
||
Уточнены local filtering, private portfolio/shared calendars, предыдущий
|
||
период дохода и уже согласованный applied period событий. Исторические ADR
|
||
сохранены; отдельные прежние ограничения CURRENCY-card и налогового смысла
|
||
dividend_net не скрыты и не объявлены исправленными этим change.
|
||
- Уточнение evidence MOEX: успешный отсутствующий block даёт [] по существующему
|
||
MoexClient и его unit test `treats a successful response without the requested
|
||
block as no events`. Название старого e2e case про missing block моделирует
|
||
rejected adapter promise, то есть source failure; оно не доказывает отказ
|
||
реального adapter при отсутствующем block. Поведение adapter не менялось и
|
||
соответствует delta scenario; повреждённый block/transport error — иной случай.
|
||
- Docs `npm run verify`: **46 Markdown files, 0 issues**, relative links/anchors
|
||
и diff passed. Изменённый label в существующей Mermaid sequence проверен по
|
||
PUT transaction flow и синтаксису; доступного локального Mermaid renderer нет,
|
||
**отрисовка диаграммы не проверена**. Это явно допустимое ограничение 7.4;
|
||
Markdown gate не выдаётся за render proof. Нового renderer/dependency нет.
|
||
- Backend production/tests не менялись в этом checkpoint; результаты 7.2,
|
||
SQLite/crash/durability/rollback и versioned performance fixture актуальны.
|
||
Backend OpenAPI и frontend snapshot по-прежнему побайтово равны.
|
||
Серверный максимум p95 **382.6 ms** в профиле Design, client p95 до **3556.4 ms**;
|
||
synthetic RPC boundary **42913 → 0**. Реальный broker network/production
|
||
rollout этим не измерены. Рабочая пользовательская БД не использовалась.
|
||
- Native gates: `openspec schema validate wealth-ledger-sdd --verbose`,
|
||
`openspec validate persist-tbank-data --type change --strict --store wealth-ledger-specs`,
|
||
`openspec validate --specs --strict --store wealth-ledger-specs` passed
|
||
(**25 main specs / 0 failed**); `npm run verify` specs и final diff checks passed.
|
||
Long requirement INFO не является validation failure. Проверены staged,
|
||
unstaged и новые файлы; root/dependencies/main specs/чужие changes сохранены.
|
||
- Implementation-owned work завершена. Independent review перед archive,
|
||
archive/main-spec sync, commits/push и deployment этим checkpoint не выполняются.
|
||
|
||
#### Requirement evidence index
|
||
|
||
Здесь B — backend, F — frontend; пути служат адресами evidence, не входами CI
|
||
соседнего repo. Результаты запусков приведены в checkpoint соответствующих задач.
|
||
|
||
- **B-access:** `test/tbank-connection.e2e-spec.ts`, `test/tbank-local-reads.e2e-spec.ts`.
|
||
- **B-ops:** `test/tbank-operations-persistence.e2e-spec.ts`,
|
||
`test/tbank-operations-sync.e2e-spec.ts` (включая SIGKILL и concurrent reader).
|
||
- **B-ledger:** `test/tbank-ledger-local.e2e-spec.ts`.
|
||
- **B-income:** `test/tbank-income-local.e2e-spec.ts`, income period/analytics unit tests.
|
||
- **B-catalog:** `test/tbank-catalog-local.e2e-spec.ts`, `test/tbank-catalog-discovery.e2e-spec.ts`.
|
||
- **B-candles:** `test/tbank-candles-persistence.e2e-spec.ts`, candle coverage unit tests.
|
||
- **B-events:** `test/upcoming-events.e2e-spec.ts`, `src/integrations/moex/moex.client.spec.ts`.
|
||
- **B-sync:** `test/tbank-screen-sync.e2e-spec.ts`.
|
||
- **B-perf:** `test/tbank-read-baseline.e2e-spec.ts`, `test/fixtures/tbank-read-persistent.json`.
|
||
- **F-accounts:** `AccountsPage.test.tsx`, `BrokerageAccountList.test.tsx` и viewport stories.
|
||
- **F-overview:** `AccountPage.test.tsx`, `AccountPage.vm.test.tsx`, `AllAccounts.test.tsx`.
|
||
- **F-ledger:** `AccountOperationsPage.test.tsx`, filters tests и instrument page tests.
|
||
- **F-income:** `AccountIncomePage.test.tsx`, filters tests; browser comparisons.
|
||
- **F-events:** `AccountEventsPage.test.tsx`, filters tests, `BrokerageEventsPreview` consumers.
|
||
- **F-boundary:** `src/shared/api/client.test.ts`, authenticated query tests,
|
||
`src/features/tbank-connection/model/screen-sync.test.tsx`, `sync.test.tsx`.
|
||
- **UI:** browser/reduced-motion/keyboard/state checks 6.3 и final checkpoint выше.
|
||
|
||
| Capability / requirement | Tasks | Evidence |
|
||
| --- | --- | --- |
|
||
| `brokerage-account-income-analytics` — Realized income analytics is account-scoped and period-bound | 3.3, 5.3 | B-income, F-income |
|
||
| `brokerage-account-income-analytics` — Period comparisons preserve calendar and currency meaning | 3.3, 5.3 | B-income, F-income; independent previous/year states |
|
||
| `brokerage-account-income-analytics` — Realized analytics never presents an incomplete result as complete | 2.1, 3.3, 5.3 | B-ops, B-income, F-income |
|
||
| `brokerage-account-income-analytics` — Account overview has an independent current-month income summary | 3.3, 5.2 | B-income, F-overview |
|
||
| `brokerage-account-income-analytics` — Income payments remain traceable to exact Ledger Entries | 2.1, 3.3, 5.3 | B-ops, B-income, F-income; exact signed entries |
|
||
| `brokerage-account-ledger` — User can retrieve an account ledger | 3.2, 5.3 | B-access, B-ledger, F-ledger |
|
||
| `brokerage-account-ledger` — User can browse a filtered ledger | 3.2, 5.3 | B-ledger; revision-bound cursor and recovery |
|
||
| `brokerage-account-ledger` — Ledger entries preserve broker operation meaning | 2.1, 3.2 | B-ops, B-ledger; exact money and identity |
|
||
| `brokerage-account-ledger` — Account overview includes recent ledger events | 3.2, 5.2 | B-ledger, F-overview |
|
||
| `brokerage-account-ledger` — Кэш страниц журнала ограничивает локальные ресурсы | 2.1, 3.2 | REMOVED: B-ledger reopen/no RPC; persistent row cursor replaces RAM page TTL |
|
||
| `brokerage-account-upcoming-events` — User can retrieve upcoming events for an account | 3.6, 5.3 | B-events, F-events |
|
||
| `brokerage-account-upcoming-events` — Forecasts preserve event meaning and uncertainty | 3.6 | B-events; decimal, cancelled, registry, null offer |
|
||
| `brokerage-account-upcoming-events` — Upcoming events use complete source results | 3.6 | B-events; fallback/reopen/new dependency failure, MOEX adapter semantics |
|
||
| `brokerage-account-upcoming-events` — Account page presents an upcoming events list | 5.3, 6.3 | F-events, UI |
|
||
| `brokerage-account-upcoming-events` — Account overview includes upcoming events | 5.2 | F-overview, B-events |
|
||
| `brokerage-accounts` — Список активных брокерских счетов | 1.3, 3.1 | B-access; order/empty/independent summaries |
|
||
| `brokerage-accounts` — Состояния недоступности списка счетов | 1.3, 3.1 | B-access; known invalid/failed replacement/observe |
|
||
| `brokerage-accounts` — Экран списка брокерских счетов | 5.2, 6.3 | F-accounts, UI; final single-column geometry |
|
||
| `brokerage-accounts` — Клиентские состояния ошибки списка счетов | 4.3, 5.2 | F-accounts, F-boundary |
|
||
| `frontend-data-resilience` — Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio | 4.3, 5.1–5.4, 6.3 | F-boundary, F-accounts, F-overview, F-income, F-events, UI |
|
||
| `portfolio-view` — Получение Portfolio выбранного Brokerage Account | 3.1 | B-access; blocked upstream/reopen/local membership |
|
||
| `portfolio-view` — Свежесть и fallback полного Portfolio Snapshot | 3.1 | B-access; stale >5min/metadata overlay/late revision fence |
|
||
| `portfolio-view` — Состояния и ошибки Portfolio на клиенте | 5.1–5.2, 6.3 | F-overview, F-boundary, UI |
|
||
| `tbank-data-sync` — Все экраны читают сохранённые данные без ожидания T-Bank | 1.2, 3.1–3.6, 6.2 | B-access, B-ledger, B-income, B-catalog, B-candles, B-events, B-perf |
|
||
| `tbank-data-sync` — Обновление запускается только запросом с учётом свежести | 2.2–2.3, 3.1–3.6 | B-ops, B-access, B-catalog, B-candles; TTL/observe/no startup work |
|
||
| `tbank-data-sync` — Ручное обновление ограничено текущим экраном | 4.1, 5.1–5.4 | B-sync, F-boundary, F-ledger, F-income, UI |
|
||
| `tbank-data-sync` — Первая загрузка приоритизирует экран и продолжает историю | 2.3, 3.5 | B-ops priority/replay/unknown floor; B-candles prefetch |
|
||
| `tbank-data-sync` — Полнота подтверждается успешным покрытием интервалов | 2.1–2.3, 3.2–3.3 | B-ops, B-ledger, B-income; pages ≠ completeness |
|
||
| `tbank-data-sync` — Сверка операций сохраняет идентичность и прежний результат | 2.1, 6.1 | B-ops; atomic quarter/all publish and separate reader |
|
||
| `tbank-data-sync` — Прогресс переживает перезапуск и одновременные запросы | 2.2, 6.1 | B-ops, B-candles, B-catalog; SIGKILL/reopen/coalescing/fences |
|
||
| `tbank-data-sync` — Общие данные инструментов отделены от личных | 1.2, 3.4–3.6 | B-catalog, B-events; two users/shared sources/private forecasts |
|
||
| `tbank-data-sync` — Локальная проверка доступа сохраняет границу подключения | 1.3, 4.3 | B-access, B-sync, F-boundary |
|
||
| `tbank-data-sync` — Завершённость свечей подтверждается источником | 3.5 | B-candles; incomplete prior day/current empty/closed gaps/failed force |
|
||
| `tbank-data-sync` — Интерфейс различает свежесть полноту и состояние работы | 4.1–4.3, 5.1–5.4, 6.3 | B-sync, F-boundary, F-income, UI |
|
||
| `tbank-data-sync` — Быстродействие и сокращение запросов проверяются измерениями | 6.2 | B-perf; 23×100, 10 clients, server p95, 20-way stale coalescing |
|
||
|
||
|
||
### Checkpoint — feature commit verification, 2026-09-26
|
||
|
||
- Implementation-owned status remains **27/27**; archive/main-spec synchronization
|
||
and release preparation remain deferred by the Change Owner.
|
||
- Fixed journal regressions after implementation: a current-day or paginated
|
||
moving period preserves confirmed completeness; the moving requested end no
|
||
longer changes `stateVersion` between unchanged status/observe reads. Actual
|
||
coverage changes still change the version. Disposable SQLite regressions prove
|
||
these outcomes without additional operations RPC.
|
||
- Fresh `npm ci` completed in all four affected repositories. Docs required a
|
||
retry with network access after the configured Nexus host returned ENOTFOUND;
|
||
dependencies and lockfiles were not changed.
|
||
- Backend `npm run verify` passed: **37 suites / 193 unit tests**, lint, both
|
||
typechecks and build. Frontend `npm run verify` passed: **53 suites / 307 tests**,
|
||
OpenAPI/type/lint/dependency gates, production and Storybook builds. Generated
|
||
backend OpenAPI remains byte-identical to the explicitly supplied frontend
|
||
snapshot. Docs verify: **46 files / 0 issues**. Native schema/change/main-spec
|
||
validation passed; apply reports **27 complete / 0 remaining**.
|
||
- Full backend `npm run test:e2e` passed in disposable Linux Docker:
|
||
**21 suites / 226 tests**, including runtime OpenAPI, migrations, financial
|
||
integrity, crash/restart, concurrency and the persisted read budget. Current
|
||
tracked source was copied into the existing development image; dependency
|
||
lock contents match exactly after excluding only root package version.
|
||
Node **24.21.0**, **4 CPU / 8 GiB**, no network, no host data volumes.
|
||
- This repeat of the Design profile measured **2300 warm reads**, maximum server
|
||
**p95 215.7 ms**, synthetic RPC **42913 → 0**. The original versioned measurement
|
||
remains in `test/fixtures/tbank-read-persistent.json`; the repeat is recorded in
|
||
`/tmp/wealthledger-feature-linux-e2e-final.log` and
|
||
`/tmp/wealthledger-feature-budget.json`. This is not a real-broker or production
|
||
latency measurement and does not establish a 500 ms browser response budget.
|
||
- Host macOS full HTTP verification is **not green**: two attempts aborted in
|
||
the native `better-sqlite3` statement cleanup with Node
|
||
`RemoveEnvironmentCleanupHook`. The same authentication suite and the complete
|
||
HTTP gate passed in Linux; no dependency workaround or application change was
|
||
introduced for the host failure. Earlier rollback/durability and browser
|
||
evidence remains applicable; Mermaid rendering remains unverified as recorded
|
||
in the preceding checkpoint.
|
||
- Staged secret scans and whitespace checks passed. Three known public
|
||
`income/yearAgo` resource identifiers have narrowly scoped Gitleaks comments;
|
||
a false positive in the Design delivery-map terminology was reworded without
|
||
changing its meaning. No credentials, working database, local backups or
|
||
unrelated active changes enter the feature commits.
|