spec: allow warning and retry after exhausted read retries (WealthLedger/specs#79) (#80)
Specs security / security (push) Successful in 7s
Specs verify / verify (push) Successful in 10s

This commit was merged in pull request #80.
This commit is contained in:
2026-11-03 07:45:09 +03:00
parent 8b2b742e52
commit 0469756d3b
9 changed files with 61 additions and 21 deletions
@@ -113,8 +113,9 @@ totals, comparisons, buckets или
breakdown как полный результат. При временной недоступности клиент MUST
сохранять предыдущий полный результат той же выборки либо показывать
нейтральную недоступность соответствующего расчёта без технических сообщений
и ручного повтора. Восстановление SHALL выполняться автоматически по
`frontend-data-resilience`.
и ручного повтора, пока автоматические повторы не исчерпаны; после их исчерпания
применяются предупреждение и «Повторить» по `frontend-data-resilience`.
Восстановление SHALL выполняться автоматически по `frontend-data-resilience`.
Доступные независимые части MUST оставаться видимыми; неполное сравнение MUST
обозначаться как недоступное без нулевой базы и окончательной разницы. Успешный
@@ -148,7 +149,7 @@ summary «Получено купонами и дивидендами» за п
Пустой или неуспешный расчёт MUST оставаться локальным состоянием блока и
MUST NOT заменять успешно отображённый Portfolio или другие блоки обзора.
Временная ошибка обновления MUST сохранять доступную сводку той же выборки без
предупреждения и ручного повтора. При отсутствии результата SHALL показываться
предупреждения и ручного повтора, пока автоматические повторы не исчерпаны. При отсутствии результата SHALL показываться
нейтральная недоступность после первичного ожидания с автоматическим восстановлением.
#### Scenario: Обзор показывает доход текущего месяца
@@ -70,7 +70,7 @@
показываются в заголовке группы. Неуспешный или пустой запрос MUST оставаться локальным состоянием
блока и MUST NOT заменять успешно отображённый Portfolio. При временном сбое
обновления блок MUST сохранять доступные записи без технического предупреждения
или ручного повтора. При отсутствии результата он SHALL показывать первичное
или ручного повтора, пока автоматические повторы не исчерпаны. При отсутствии результата он SHALL показывать первичное
ожидание либо нейтральную недоступность, автоматически восстанавливая чтение.
Неподтверждённая пустота MUST NOT представляться отсутствием операций.
@@ -185,14 +185,15 @@
обновления и восстанавливать чтение автоматически по `frontend-data-resilience`.
Период, категории и выбранная страница MUST сохраняться; результат другой
выборки MUST NOT подменять текущую. Страница MUST NOT показывать время получения,
технические статусы или действия ручного повтора. Даты операций, фильтры,
технические статусы или действия ручного повтора до исчерпания автоматических
повторов (далее по `frontend-data-resilience`). Даты операций, фильтры,
действия их применения и переходы по страницам MUST оставаться доступными.
При отсутствии результата SHALL применяться первичное ожидание и нейтральная
недоступность, а не сообщение об отсутствии операций до подтверждения полноты.
#### Scenario: Обновление журнала временно не удалось
- **WHEN** для применённого периода и страницы уже есть записи, а обновление завершается временной ошибкой
- **THEN** записи и параметры просмотра сохраняются без предупреждения и кнопки повтора до автоматического восстановления
- **THEN** записи и параметры просмотра сохраняются без предупреждения и кнопки повтора до автоматического восстановления либо до исчерпания автоматических повторов
#### Scenario: Следующая страница ещё не получена
- **WHEN** пользователь перешёл к следующей странице, но её загрузка временно не удалась
@@ -100,7 +100,8 @@ MUST объяснять, что прогноз основан на позици
При временном сбое обновления страница MUST сохранять ранее доступный результат
той же выборки с его исходными `calculatedAt` и окном, без индикации
собственного чтения и ручного повтора. Состояние источника из `meta`, включая
собственного чтения и ручного повтора до исчерпания автоматических повторов
(затем применяются предупреждение и «Повторить» по `frontend-data-resilience`). Состояние источника из `meta`, включая
неуспех последней часовой попытки и неполноту, MUST представляться по
`frontend-data-resilience`. При отсутствии результата SHALL показываться
первичное ожидание либо нейтральная недоступность с автоматическим
@@ -117,7 +118,7 @@ MUST скрывать личные данные независимо от нал
#### Scenario: Ошибка страницы
- **WHEN** запрос будущих событий завершается временной ошибкой
- **THEN** страница сохраняет доступный результат той же выборки либо показывает нейтральную недоступность без ручного повтора, восстанавливая чтение автоматически и не выдавая частичные данные за полный прогноз
- **THEN** страница сохраняет доступный результат той же выборки либо показывает нейтральную недоступность без ручного повтора до исчерпания автоматических повторов, восстанавливая чтение автоматически и не выдавая частичные данные за полный прогноз
#### Scenario: Прогнозный дивиденд с неизвестной суммой
- **WHEN** прогноз содержит дивиденд с известной датой реестра, но без суммы
@@ -71,7 +71,8 @@
в течение 60 секунд. После истечения этого срока открытие или возвращение
на экран SHALL инициировать получение актуального списка; имеющийся Client
Cached Snapshot MUST оставаться видимым во время обновления и после временной
ошибки без индикации собственного чтения и действий повтора.
ошибки без индикации собственного чтения и действий повтора, пока автоматические
повторы не исчерпаны (далее по `frontend-data-resilience`).
Автоматическое восстановление SHALL соответствовать `frontend-data-resilience`.
Открытый экран MAY периодически перечитывать backend-результат, сохраняя
видимый snapshot, и MUST NOT создавать импорт T-Bank. Состояние источника из
@@ -124,7 +125,7 @@ Money-итогов в исходных валютах и обозначать н
#### Scenario: Ошибка фонового обновления не скрывает snapshot
- **WHEN** обновление устаревшего списка завершается временной ошибкой при наличии последнего успешного Client Cached Snapshot
- **THEN** клиент сохраняет snapshot видимым без предупреждения и ручного повтора и восстанавливает получение данных автоматически
- **THEN** клиент сохраняет snapshot видимым без предупреждения и ручного повтора до исчерпания автоматических повторов и восстанавливает получение данных автоматически
#### Scenario: Карточка ограничивает валютные итоги
- **WHEN** доступная сводка счёта содержит итоги в трёх или более валютах
@@ -18,7 +18,9 @@ Portfolio и других экранов чтения при фоновом об
выборки как результат новой.
Доступный результат MUST оставаться видимым без индикаторов фонового чтения
клиента, технических предупреждений об этом чтении и действий ручного повтора.
клиента, технических предупреждений об этом чтении и действий ручного повтора,
пока автоматические повторы не исчерпаны; после их исчерпания применяется
требование «Временные сбои чтения восстанавливаются автоматически».
Frontend MUST NOT подменять внутренние признаки свежести и полноты, успешное
время источника или ошибку обновления только ради отсутствия их отображения.
Client Cached Snapshot MUST оставаться отличным от server-side fallback;
@@ -43,14 +45,14 @@ MUST NOT возвращать их на экран.
#### Scenario: Resource сохраняется после неуспешной часовой попытки
- **WHEN** response содержит полный `data` и `meta`, обозначающий неуспех последней часовой попытки
- **THEN** frontend сохраняет `data` и его исходное время видимыми и отдельно обозначает неуспех попытки, не предлагая ручной повтор
- **THEN** frontend сохраняет `data` и его исходное время видимыми и отдельно обозначает неуспех попытки, не предлагая запуск повторного получения данных из источника
#### Scenario: Обновление Portfolio завершается ошибкой после успешного ответа
- **WHEN** экран Brokerage Account уже показывает Client Cached Snapshot Portfolio, а последующее обновление этого же Portfolio завершается временной ошибкой
- **THEN** frontend сохраняет Portfolio видимым без предупреждения и ручного повтора, а восстановление выполняется автоматически
- **THEN** frontend сохраняет Portfolio видимым без предупреждения и ручного повтора, а восстановление выполняется автоматически, пока автоматические повторы не исчерпаны
#### Scenario: Server-side fallback и client cached snapshot различаются
- **WHEN** backend возвращает Portfolio с `isStale` либо фоновое обновление Client Cached Snapshot завершается временной ошибкой
- **WHEN** backend возвращает Portfolio с `isStale` либо фоновое обновление Client Cached Snapshot завершается временной ошибкой, а автоматические повторы ещё не исчерпаны
- **THEN** frontend сохраняет доступные данные без технических сообщений и не подменяет один внутренний вид состояния другим
#### Scenario: Подтверждённая пустота переживает фоновую ошибку
@@ -75,7 +77,17 @@ Frontend SHALL автоматически повторять временно н
получение необходимых текущему экрану данных без ручного обновления. Повторы
одной попытки MUST иметь конечный предел и паузы, исключающие непрерывную
череду запросов. При исчерпании предела доступные данные SHALL сохраняться,
а при их отсутствии SHALL показываться локальная недоступность. Возвращение сети,
а при их отсутствии SHALL показываться локальная недоступность. На экранах
Account, Accounts, Income, Operations, Events и секций деталей инструмента при исчерпании предела
frontend SHALL дополнительно показывать неблокирующее локализованное предупреждение
о неудачном обновлении и действие «Повторить» рядом с затронутым результатом либо
локальной недоступностью. Действие MUST повторять только чтение (GET) затронутого
запроса, не запускать получение данных из источника и не менять выбранные
фильтры, период, открытые разделы и ввод; успешное чтение MUST снимать
предупреждение и MUST NOT сообщать об успехе. Предупреждение MUST NOT дублировать
состояние источника из `meta` и MUST NOT изменять `Portfolio.isStale`. На остальных
экранах чтения, включая поиск, диапазон графика, карты и настройки подключения,
предупреждение и действие повтора MUST NOT показываться. Возвращение сети,
возвращение пользователя к открытому экрану и повторное открытие экрана MUST
возобновлять получение отсутствующих или требующих обновления данных без
перезагрузки страницы. Свежий полный результат MUST NOT требовать обращения
@@ -101,6 +113,18 @@ Frontend SHALL автоматически повторять временно н
- **WHEN** временная недоступность сохраняется после конечного предела автоматических попыток
- **THEN** приложение прекращает серию повторов, сохраняет доступный результат либо локальную недоступность без бесконечной загрузки и ожидает следующего события восстановления
#### Scenario: Повторы исчерпаны при сохранённом результате
- **WHEN** на экране Account, Accounts, Income, Operations, Events либо в секции деталей инструмента автоматические повторы исчерпаны, а ранее полученный результат остаётся доступным
- **THEN** результат и его исходное состояние источника остаются видимыми, рядом показываются неблокирующее предупреждение о неудачном обновлении и действие «Повторить», а активация действия повторяет только чтение затронутого запроса и после успеха снимает предупреждение
#### Scenario: Повторы исчерпаны без результата
- **WHEN** на тех же экранах автоматические повторы исчерпаны, а результата выборки нет
- **THEN** локальная недоступность содержит действие «Повторить», повторяющее только чтение затронутого запроса, и результат одной секции деталей не блокирует восстановление остальных
#### Scenario: Поиск, график и карты остаются тихими
- **WHEN** автоматические повторы исчерпаны при чтении результата поиска, диапазона графика, карт либо настроек подключения
- **THEN** приложение не показывает предупреждение и действие повтора и сохраняет прежнее локальное поведение
#### Scenario: Сеть или пользователь вернулись
- **WHEN** после временного сбоя восстановилась сеть либо пользователь вернулся к экрану с отсутствующим или требующим обновления результатом
- **THEN** получение данных возобновляется автоматически для текущей выборки и при успехе заменяет состояние недоступности содержимым
@@ -79,7 +79,8 @@ MUST NOT заменять уже доступный контекст skeleton pl
ожидание соответствующей области. После неуспешного завершения получения
либо истечения ограниченного времени первичного ожидания область MUST переходить
в спокойное локализованное состояние недоступности без технических подробностей
и ручного повтора. Это состояние MUST NOT утверждать, что результат пустой,
и ручного повтора, пока автоматические повторы не исчерпаны (далее по
`frontend-data-resilience`). Это состояние MUST NOT утверждать, что результат пустой,
или требовать перезагрузки страницы. Продолжающееся автоматическое восстановление
MUST NOT заставлять область постоянно переключаться между недоступностью и
skeleton. После успешного получения содержимое SHALL появляться автоматически.
@@ -94,7 +95,7 @@ skeleton. После успешного получения содержимое
#### Scenario: Первое получение данных не удалось
- **WHEN** у области нет результата и первоначальная загрузка завершилась ошибкой или превысила ограниченное время ожидания
- **THEN** область показывает нейтральную недоступность без кнопки повтора, вымышленных данных и бесконечного индикатора занятости
- **THEN** область показывает нейтральную недоступность без кнопки повтора до исчерпания автоматических повторов, вымышленных данных и бесконечного индикатора занятости
#### Scenario: Восстановление продолжается после недоступности
- **WHEN** область уже показывает недоступность и выполняется очередная разрешённая попытка восстановления
@@ -30,7 +30,10 @@ Frontend SHALL сохранять локальное отображение из
Account, Portfolio и T-Bank connection. Эти состояния MUST NOT заменяться
глобальным fallback. Временная ошибка фонового чтения MUST сохранять доступный
результат без предупреждения об устаревании, технической ошибки и ручного
повтора. При отсутствии результата SHALL показываться локальная недоступность
повтора, пока автоматические повторы не исчерпаны; для Brokerage Account и
Portfolio после их исчерпания применяется `frontend-data-resilience`
(предупреждение и «Повторить»), для T-Bank connection поведение остаётся тихим.
При отсутствии результата SHALL показываться локальная недоступность
с автоматическим восстановлением. Подтверждённая необходимость входа,
восстановления подключения или выбора доступного счёта MUST сохранять понятное
объяснение и соответствующее действие, не маскируясь сохранёнными личными данными.
@@ -15,7 +15,11 @@
об успехе либо временной ошибке такого обновления. Приложение MUST NOT предоставлять
кнопки или иные действия ручного обновления и повторной загрузки, включая их
иконные варианты. Эти сведения MUST NOT переноситься в уведомления, подсказки
или объявления вспомогательных технологий. Даты операций, выплат, открытия
или объявления вспомогательных технологий. Единственное исключение — предупреждение
о неудачном обновлении и действие «Повторить» на экранах Account, Accounts, Income, Operations, Events и секций деталей инструмента после
исчерпания конечной серии автоматических повторов (по `frontend-data-resilience`);
запрет по-прежнему действует до этого момента, на остальных экранах и для иконных
вариантов обновления. Даты операций, выплат, открытия
счёта и выбранных периодов MUST сохранять свой предметный смысл.
Запрет технических действий MUST NOT удалять применение фильтров, переходы между
@@ -24,9 +28,13 @@
сохранённый ввод обычным действием формы.
#### Scenario: Фоновая загрузка завершилась ошибкой
- **WHEN** на любом из перечисленных экранов уже есть доступный результат и его фоновое обновление временно не удалось
- **WHEN** на любом из перечисленных экранов уже есть доступный результат и его фоновое обновление временно не удалось, а автоматические повторы ещё не исчерпаны
- **THEN** результат остаётся видимым без предупреждения, времени получения, индикатора, уведомления и действия ручного повтора
#### Scenario: Автоматические повторы исчерпаны на экране инвестиций
- **WHEN** на экране Account, Accounts, Income, Operations, Events либо в секции деталей инструмента автоматические повторы исчерпаны
- **THEN** экран показывает неблокирующее предупреждение и действие «Повторить» по `frontend-data-resilience`, не показывает время получения, индикатор или уведомление и не объявляет их вспомогательным технологиям как успех или прогресс
#### Scenario: Фоновая загрузка завершилась успешно
- **WHEN** приложение получает обновлённые данные без явного действия сохранения со стороны пользователя
- **THEN** содержимое обновляется без сообщения об успешной загрузке и без переноса фокуса
@@ -248,7 +248,7 @@ Portfolio и предложить возврат к списку счетов.
#### Scenario: Первичный Portfolio пока недоступен
- **WHEN** данных Portfolio нет, а первичное получение не удалось или превысило ограниченное время ожидания
- **THEN** клиент показывает нейтральную недоступность без кнопки повтора и автоматически заменяет её содержимым после успешного восстановления
- **THEN** клиент показывает нейтральную недоступность без кнопки повтора до исчерпания автоматических повторов и автоматически заменяет её содержимым после успешного восстановления
#### Scenario: Требуется восстановить подключение
- **WHEN** клиент получает `TBANK_NOT_CONNECTED` или `INVALID_TBANK_TOKEN` при наличии сохранённого личного Portfolio