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

82 lines
12 KiB
Markdown
Raw Permalink 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.
# hourly-investment-sync Specification
## Purpose
Определяет независимое от открытых экранов часовое обновление личных инвестиционных данных и безопасно наблюдаемый результат последней попытки.
## Requirements
### Requirement: Часовой обход личных инвестиционных данных
Система SHALL начинать первый часовой обход после успешного подключения T-Bank и последующие обходы не ранее чем через 60 минут от начала предыдущей попытки этого подключения. После простоя система MUST выполнить не более одного актуального обхода и MUST NOT воспроизводить пропущенные часы. Неуспешная попытка MUST NOT повторяться ранее следующего часового срока. Перекрывающиеся обходы MUST NOT выполняться: срок, наступивший во время выполняющегося обхода, MUST быть пропущен и MUST NOT ставиться в очередь; следующий обход становится допустимым только в следующий 60-минутный срок, отсчитанный от начала выполнявшейся попытки. Обход MUST обновлять доступные счета, Portfolio каждого доступного счёта, изменяемый хвост операций и будущие события по бумагам текущего Portfolio. Он MUST NOT повторно загружать полные прошлые интервалы операций, завершённые свечи или полную рыночную историю и MUST NOT зависеть от открытия frontend-экрана.
#### Scenario: Первое подключение
- **WHEN** User успешно подключает T-Bank между часовыми сроками
- **THEN** первый обход начинается без ожидания следующего календарного часа
#### Scenario: Возобновление после простоя
- **WHEN** backend запускается после пропуска нескольких часовых сроков
- **THEN** система выполняет один актуальный обход без синтетических прошлых обновлений
#### Scenario: Перекрытый срок
- **WHEN** предыдущий обход всё ещё выполняется в момент очередного срока
- **THEN** система не начинает второй обход и не ставит пропущенный обход в очередь
#### Scenario: Длительный обход пропускает один срок
- **WHEN** обход начался в 10:00, всё ещё выполняется в 11:00 и завершился до 12:00
- **THEN** система не запускает обход в 11:00 и может начать следующий не ранее 12:00
### Requirement: Последний результат обхода доступен только для наблюдения
Система SHALL предоставлять авторизованному User результат последнего обхода только в границе его текущего подключения: время начала, состояние выполнения, полного успеха, частичного успеха либо неуспеха и безопасный перечень проблемных счетов или разделов. Это состояние MUST быть доступно в `meta` каждого затронутого resource read вместе с freshness, полнотой и доступностью его `data`. Успех одного счёта или раздела MUST сохраняться независимо от ошибки другого; ошибка MUST NOT заменять его последнее успешное состояние или время. Итог попытки MUST определяться фактическим результатом каждого обязательного шага обхода: попытка, не завершившая обязательный шаг, MUST обозначаться частичным успехом либо неуспехом и MUST NOT обозначаться полным успехом. Отсутствие состоявшейся попытки MUST отличаться от успешной попытки. Наблюдение результата MUST NOT предоставлять способ начать личную синхронизацию.
#### Scenario: Частичный успех
- **WHEN** Portfolio одного доступного счёта обновился, а другого не обновился
- **THEN** новый Portfolio первого сохраняется, прежний успешный Portfolio второго остаётся доступным, а результат обхода обозначает частичный успех и проблемный счёт
#### Scenario: Наблюдение не запускает обход
- **WHEN** User запрашивает результат последнего обхода
- **THEN** система возвращает доступный сохранённый результат без нового обращения к T-Bank
#### Scenario: Старая граница подключения
- **WHEN** User заменил либо удалил подключение и запрашивает результат прежнего обхода
- **THEN** система не раскрывает результат прежней границы подключения
#### Scenario: Сбой после частичного обновления
- **WHEN** попытка прервана ошибкой либо сбоем сохранения после обновления Portfolio одного доступного счёта
- **THEN** результат попытки обозначает частичный успех с проблемными шагами, а не полный успех, а обновлённый Portfolio сохраняется
#### Scenario: Сбой до первого обновления
- **WHEN** попытка прервана до обновления любого обязательного шага
- **THEN** результат попытки обозначает неуспех, а не полный успех
### Requirement: Каждая попытка обхода достигает итога в ограниченное время
Каждая начатая попытка часового обхода MUST достигать итогового состояния в ограниченное время. Ожидание завершения каждого обязательного шага MUST быть ограничено; шаг, не завершившийся в это ограничение, MUST быть учтён как проблемный, а попытка MUST быть закрыта частичным успехом либо неуспехом после того, как каждый обязательный шаг достиг терминального результата либо был учтён как проблемный. Истечение ограничения MUST NOT отменять уже начатые шаги.
#### Scenario: Шаг не завершается
- **WHEN** обязательный шаг не покидает состояние выполнения дольше ограничения ожидания
- **THEN** шаг учитывается как проблемный, попытка закрывается частичным успехом либо неуспехом, а её состояние перестаёт быть выполняющимся
#### Scenario: Наблюдение не ждёт без ограничения
- **WHEN** попытка не может завершиться из-за незавершённых шагов
- **THEN** наблюдение результата получает итоговое состояние в ограниченное время и не ожидает завершения бесконечно
### Requirement: Восстановление после сбоя сохранения не блокирует последующие обходы
Если попытка осталась в состоянии выполнения после сбоя завершения шага, публикации результата либо закрытия попытки, система MUST привести её к диагностируемому итоговому состоянию: частичный успех либо неуспех с сохранёнными результатами шагов, а не полный успех. Последующий обход MUST становиться допустимым по обычному правилу срока, отсчитанному от начала этой попытки. Восстановление MUST NOT создавать перекрывающийся обход и MUST NOT повторять уже полученные результаты шагов.
#### Scenario: Потерянное закрытие попытки
- **WHEN** закрытие попытки не сохранилось, а процесс продолжает работать
- **THEN** система закрывает попытку итогом из фактических результатов шагов, наблюдение получает итоговое состояние, а следующая допустимая попытка может стартовать
#### Scenario: Перезапуск процесса
- **WHEN** процесс остановился после начала попытки и запускается снова
- **THEN** брошенная попытка обозначается частичным успехом либо неуспехом с сохранёнными результатами шагов, а новый обход начинается не ранее следующего часового срока от её начала
### Requirement: Устаревшая публикация не влияет на актуальную попытку
Результат шага попытки, у которой появился преемник, MUST отклоняться как устаревший: он MUST NOT обновлять данные и MUST NOT учитываться в итоге актуальной попытки. Шаг устаревшей попытки MUST наблюдаться как устаревший относительно актуального преемника. Результат шага текущей попытки, полученный до фиксации её итога, MUST сохраняться и учитываться в этом итоге независимо от того, наступил ли он до или после истечения ограничения ожидания.
#### Scenario: Поздняя публикация после появления преемника
- **WHEN** шаг старой попытки завершается после запуска следующей попытки
- **THEN** его результат отклоняется как устаревший, данные не обновляются, а итог актуальной попытки не меняется
#### Scenario: Поздняя публикация до фиксации итога
- **WHEN** шаг завершился после истечения ограничения ожидания, но итог его попытки ещё не зафиксирован
- **THEN** его результат сохраняется и учитывается при выводе итога этой попытки