Files
specs/openspec/changes/hourly-portfolio-sync-history/tasks.md
T
ksv741 b24a686188
Specs security / security (push) Successful in 7s
Specs verify / verify (push) Successful in 9s
Conventional commits / commits (pull_request) Successful in 10s
Specs security / security (pull_request) Successful in 7s
Specs verify / verify (pull_request) Successful in 9s
spec: define hourly portfolio sync history
2026-10-09 09:05:04 +03:00

69 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 1. Данные и граница доступа
- [x] 1.1 [backend] Добавить совместимое хранение точек оценки и видимости истории отдельно от revision; сохранять по валютам только полную оценку в той же транзакции, что и успешно заявленный снимок, с дедупликацией попытки.
- **Covers:** `portfolio-value-history` — `Полная оценка становится точкой истории`; `portfolio-view` — `Свежесть и fallback полного Portfolio Snapshot`
- **Verification:** Изолированная SQLite с применёнными прежними migrations: новая миграция сохраняет старые данные; повторная/поздняя попытка не создаёт лишних точек, неизвестная цена не записывает ни одной валюты, неуспешная публикация сохраняет снимок и историю.
- [x] 1.2 [backend] Связать видимость истории с успешными PUT/DELETE подключения и публикацией полного membership; закрыть доступ старой revision и оставить историю для повторно подтверждённого accountId.
- **Covers:** `portfolio-value-history` — `История переживает смену подключения без потери приватности`; `tbank-connection` — `Создание и замена подключения T-Bank`; `tbank-connection` — `Удаление подключения T-Bank`
- **Verification:** SQLite/HTTP проверки смены токена, отключения, отсутствующего и вернувшегося счёта, ошибки membership, чужого User и поздней попытки; прежние текущие datasets не раскрываются и история не исчезает.
## 2. Часовой обход и локальные чтения
- [x] 2.1 [backend] Применить выбранный в Design Solution Assessment: один native timer и durable conditional reservation для запуска и восстановления часовой попытки без параллельного обхода.
- **Covers:** `hourly-investment-sync` — `Часовой обход личных инвестиционных данных`
- **Verification:** SQLite/integration сценарии первого подключения, рестарта до и после 60 минут, пропущенных часов, перекрытого тика, замены revision и перезапуска незавершённой работы; ни один сценарий не создаёт конкурирующих попыток.
- [x] 2.2 [backend] Оркестрировать подтверждённый membership, портфели счетов, изменяемый хвост операций и события через существующих владельцев источников; агрегировать результат последней попытки и открыть только read-only статус авторизованному User.
- **Covers:** `hourly-investment-sync` — `Часовой обход личных инвестиционных данных`; `hourly-investment-sync` — `Сохранность и статус последней попытки`; `brokerage-account-upcoming-events` — `Upcoming events use complete source results`
- **Verification:** Integration/HTTP проверки: ошибка одного счёта или события даёт частичный статус с безопасным разделом, успешные источники публикуются, старый прогноз и время переживают сбой; чужой User/старая revision не видны, OpenAPI contract parity проходит.
- [x] 2.3 [backend] Перевести обычные GET счетов, портфеля и прогноза на локальное чтение без запуска обновления личных источников; согласовать часовую свежесть, первый незавершённый обход и отдельно отображаемый сбой.
- **Covers:** `portfolio-view` — `Свежесть и fallback полного Portfolio Snapshot`; `brokerage-accounts` — `Состояния недоступности списка счетов`; `brokerage-account-upcoming-events` — `Upcoming events use complete source results`
- **Verification:** HTTP/integration проверки локального ответа без RPC при missing/stale, неизвестного membership, временного сбоя, известного invalid token, неполной оценки и доступности последнего успешного снимка.
- [x] 2.4 [backend] Оставить для журнала запуск только первичной загрузки отсутствующих интервалов; обновление изменяемого хвоста перенести в часовой обход, не перечитывая полные прошлые интервалы.
- **Covers:** `brokerage-account-ledger` — `Отсутствующий исторический интервал загружается только впервые`; `hourly-investment-sync` — `Часовой обход личных инвестиционных данных`
- **Verification:** SQLite/integration проверка пустого полного периода, неполной страницы, повторного открытия прошлого месяца, движения конца текущего периода и неповторного чтения сохранённой истории.
## 3. Инструменты и граница публичного API
- [x] 3.1 [backend] Развязать сохранённые котировки, свечи и события от справочных payload; обновлять текущую котировку и изменяемую свечу не чаще часа, сохраняя покрытия завершённых диапазонов и полные прогнозы.
- **Covers:** `online-instrument-information` — `Рыночные и событийные данные имеют отдельную политику`; `brokerage-account-upcoming-events` — `Upcoming events use complete source results`
- **Verification:** Integration с изолированной SQLite: первая загрузка диапазона, отсутствие повторной загрузки полного прошлого диапазона, запрос свежей котировки, неудача онлайн-справочника и сохранность forecast/coverage/candles; миграция не удаляет связанные рыночные строки.
- [x] 3.2 [backend] Перевести detail, company, поиск и lookup инструментов на онлайн-ответ через существующие integration clients; отделить их ошибку от сохранённых подписей и финансовых ресурсов без самостоятельной долговременной копии.
- **Covers:** `online-instrument-information` — `Справочные сведения и поиск запрашиваются онлайн`; `portfolio-view` — `Свежесть и fallback полного Portfolio Snapshot`
- **Verification:** HTTP/service проверки повторного онлайн-запроса, совпадения UID и ticker, пустого/неоднозначного результата и upstream-сбоя при видимом сохранённом портфеле; не создаются новые долговременные detail/search/negative lookup.
- [x] 3.3 [backend] Сформировать публичный OpenAPI со статусом обхода, сохранив переходный контракт screen POST до готовности frontend.
- **Covers:** `hourly-investment-sync` — `Сохранность и статус последней попытки`; `portfolio-view` — `Состояния и ошибки Portfolio на клиенте`
- **Verification:** `npm run openapi:generate`, `npm run test:openapi-contract` и configured HTTP suite для действующего и переходного wire contract; обычный GET не инициирует screen POST.
- [x] 3.4 [backend] Проверить рост SQLite на представительном объёме и фактическую частоту upstream-вызовов; сопоставить её с действующей первичной документацией T-Bank перед настройкой частоты, выполнить штатные backend gates и durability для новой схемы.
- **Covers:** `N/A` — операционная проверка выбранного в Design хранения и scheduler, без нового пользовательского поведения.
- **Verification:** Выполнено: SQLite 617,263,104 bytes на synthetic profile (3 accounts, 300,000 operations, 200 instruments, 1,000,000 candles), persisted-read phase сделал 0 upstream calls; `npx prisma validate`, durability с pre-history baseline, `npm run test:e2e` и performance budget проходят. Ограничение `TBANK_RATE_LIMIT_PER_SECOND` (default 5 per backend instance) зафиксировано в `docs/adr/020-hourly-sync-verification-evidence.md`; production quota не расширяется.
## 4. Клиентские экраны
- [x] 4.1 [frontend] Получить опубликованный backend OpenAPI artifact и обновить локальный snapshot/generated types для статуса без импорта backend internals.
- **Covers:** `hourly-investment-sync` — `Сохранность и статус последней попытки`
- **Verification:** `npm run openapi:generate` и `npm run openapi:check` из frontend на предоставленном artifact; статус типизирован, отсутствие попытки и изоляция ошибки не заменены вымышленным успехом.
- [x] 4.2 [frontend] Удалить инвестиционные кнопки/POST ручной синхронизации и source-recovery triggers; сохранить транспортный retry только как повтор чтения, а открытые инвестиционные экраны перечитывать раз в 30 минут.
- **Covers:** `portfolio-view` — `Состояния и ошибки Portfolio на клиенте`; `brokerage-accounts` — `Экран списка брокерских счетов`; `brokerage-accounts` — `Клиентские состояния ошибки списка счетов`; `frontend-data-resilience` — `Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio`
- **Verification:** UI/query проверки 30-минутного активного экрана, прекращения опроса после ухода, сохранения снимка при сбое и повторного HTTP GET без POST; auth-refresh и действия ручных карт не меняются.
- [x] 4.3 [frontend] Показать в кабинете время/исход последнего обхода и названия проблемных счетов и разделов; справочный блок карточки отделить от позиций, событий, свечей и локальной ошибки чтения.
- **Covers:** `hourly-investment-sync` — `Сохранность и статус последней попытки`; `online-instrument-information` — `Справочные сведения и поиск запрашиваются онлайн`; `brokerage-accounts` — `Экран списка брокерских счетов`
- **Verification:** Проверки состояний `none/running/succeeded/partial/failed`, локального сбоя detail при видимых финансовых данных, доступных текстовых подписей и переноса статуса на узком экране согласно inline UI package Design revision 1.
- [x] 4.4 [frontend] Завершить клиентский переход штатными gates и сверкой критического маршрута нового подключения → первый обход → статус → сохранённый портфель на открытом экране.
- **Covers:** `N/A` — интеграционная проверка принятого UI package и публичного контракта после изменения нескольких экранов, без отдельного нового требования.
- **Verification:** `npm run verify` в frontend и наблюдаемые состояния критического маршрута с предоставленным backend OpenAPI.
## 5. Завершение перехода
- [x] 5.1 [backend] После перехода frontend убрать неиспользуемый screen POST и наблюдение прежней работы без затрагивания нового статуса обхода.
- **Covers:** `hourly-investment-sync` — `Сохранность и статус последней попытки`; `portfolio-view` — `Состояния и ошибки Portfolio на клиенте`
- **Verification:** `npm run openapi:generate`, `npm run test:openapi-contract` и configured HTTP suite: старый trigger недоступен, обычный GET и повтор чтения не запускают импорт.
## 6. Нормативная и as-built документация
- [x] 6.1 [specs] Проверить полное соответствие девяти Delta Specs одобренному Proposal и Design, сохранить точные имена Requirements и валидировать change и основные specs.
- **Covers:** `N/A` — самостоятельная проверка нормативного артефакта и согласованной границы изменения, без добавления нового поведения.
- **Verification:** `openspec schema validate wealth-ledger-sdd --verbose`, `openspec validate hourly-portfolio-sync-history --type change --strict --store wealth-ledger-specs`, `openspec validate --specs --strict --store wealth-ledger-specs`, `npm run verify` в specs.
- [x] 6.2 [docs] После проверки реализованного поведения дополнить глоссарий и объяснение свежести/истории, обновить соответствующие страницы инвестиций и зафиксировать новый ADR, который связывает изменённое решение с ADR 017, не переписывая исторический контекст.
- **Covers:** `N/A` — as-built объяснение подтверждённых решений Design в отдельном docs owner, не параллельная норма требований.
- **Verification:** Проверить маршруты чтения, локальные ссылки и смысл финансовых значений; `npm run verify` из docs.