spec: simplify runtime requirements
Specs security / security (push) Failing after 8s
Specs verify / verify (push) Successful in 10s
Conventional commits / commits (pull_request) Successful in 12s
Specs security / security (pull_request) Failing after 8s
Specs verify / verify (pull_request) Successful in 10s
Specs security / security (push) Failing after 8s
Specs verify / verify (push) Successful in 10s
Conventional commits / commits (pull_request) Successful in 12s
Specs security / security (pull_request) Failing after 8s
Specs verify / verify (pull_request) Successful in 10s
Preserve identity isolation and financial integrity while accepting cross-tab reauthentication and on-demand candle history. Align portfolio freshness with persisted reads and keep income consistency at the backend owner.
This commit is contained in:
@@ -156,7 +156,7 @@
|
||||
|
||||
### Requirement: Income payments remain traceable to exact Ledger Entries
|
||||
|
||||
В разделе «Выплаты» страница MUST показывать единый список карточек точных исполненных Ledger Entries применённого периода в исходном серверном порядке entries. Каждая выплата MUST иметь собственную сразу видимую карточку с описанием, датой, доступной identity Instrument и signed Money в исходной валюте. Страница MUST NOT добавлять внешние группировочные карточки или заголовки по Instrument либо валюте, subtotals инструмента или количество выплат инструмента. Список MUST сохранять отрицательные корректировки и повторяющиеся operation IDs как отдельные записи и MUST NOT включать записи вне аналитического итога. Отказ от группировочного UI MUST NOT отменять проверки принадлежности entries к instrumentKey, валюты и receipt count ответа или приводить к пересчёту денежных итогов на клиенте.
|
||||
В разделе «Выплаты» страница MUST показывать единый список карточек точных исполненных Ledger Entries применённого периода в исходном серверном порядке entries. Каждая выплата MUST иметь собственную сразу видимую карточку с описанием, датой, доступной identity Instrument и signed Money в исходной валюте. Страница MUST NOT добавлять внешние группировочные карточки или заголовки по Instrument либо валюте, subtotals инструмента или количество выплат инструмента. Список MUST сохранять отрицательные корректировки и повторяющиеся operation IDs как отдельные записи и MUST NOT включать записи вне аналитического итога. Backend MUST обеспечивать согласованность entries, instrumentKey, валюты и receipt count при формировании ответа из одного набора записей. Frontend SHALL доверять типизированному contract без второго runtime consistency validator и MUST NOT пересчитывать денежные итоги.
|
||||
|
||||
#### Scenario: Каждая выплата показана отдельной карточкой
|
||||
|
||||
|
||||
@@ -94,20 +94,29 @@ Portfolio Snapshot является результатом наблюдения
|
||||
- **THEN** система передаёт её как строку `"-0.5"`
|
||||
|
||||
### Requirement: Свежесть и fallback полного Portfolio Snapshot
|
||||
Система MUST кэшировать полный успешный Portfolio Snapshot отдельно для каждой пары User и Brokerage Account в памяти на 30 секунд. После истечения свежего кэша система MUST получить новый полный снимок; при временной upstream-недоступности она SHALL вернуть последний успешный полный снимок, если ему не более пяти минут, с `isStale: true`. Metadata инструмента MUST NOT влиять на успешность или свежесть Portfolio Snapshot, но MUST быть получено до формирования нового Snapshot, чтобы при доступном upstream-ответе вернуть отображаемое имя инструмента.
|
||||
Система MUST хранить последний полный успешный Portfolio Snapshot в SQLite
|
||||
с принадлежностью User, экземпляру подключения и Brokerage Account. Обычный
|
||||
GET MUST читать сохранённые данные без ожидания T-Bank; missing/stale источники
|
||||
обновляются в фоне по пользовательскому запросу. Portfolio source свеж 60 секунд.
|
||||
Ошибка обновления MUST сохранять прежний полный Snapshot и его время без
|
||||
пятиминутного лимита fallback. Metadata MUST NOT определять успешность или
|
||||
свежесть финансового Snapshot; при её отсутствии используется доступный fallback.
|
||||
|
||||
Система MUST очищать все Portfolio Snapshot User после успешной замены или удаления его T-Bank connection. Успешные metadata инструмента и подтверждённое отсутствие инструмента MUST кэшироваться глобально по FIGI на 24 часа; ошибка metadata lookup MUST NOT кэшироваться.
|
||||
Система MUST делать прежние личные datasets недоступными после успешной замены
|
||||
или удаления подключения. Поздняя работа прежнего подключения MUST NOT
|
||||
публиковаться в новом. Общие metadata и подтверждённое отсутствие инструмента
|
||||
сохраняются по UID/FIGI на 24 часа; ошибка lookup не подтверждает отсутствие.
|
||||
|
||||
#### Scenario: Свежий Snapshot
|
||||
- **WHEN** User повторно запрашивает тот же Portfolio в течение 30 секунд после успешного получения
|
||||
- **WHEN** User повторно запрашивает тот же Portfolio в течение 60 секунд после успешного получения
|
||||
- **THEN** система возвращает свежий Snapshot без нового обращения к T-Bank
|
||||
|
||||
#### Scenario: Медленный lookup инструмента
|
||||
- **WHEN** metadata инструмента ещё отсутствует и его lookup не завершился
|
||||
- **THEN** система ожидает lookup в пределах gRPC deadline и возвращает name при успешном ответе upstream
|
||||
- **THEN** система не задерживает локальный ответ ради lookup и показывает доступную identity; сохранённая успешная metadata используется последующим чтением
|
||||
|
||||
#### Scenario: Fallback после временной upstream-ошибки
|
||||
- **WHEN** обновление устаревшего Snapshot неуспешно из-за временной недоступности T-Bank, а последний полный успешный Snapshot получен не более пяти минут назад
|
||||
- **WHEN** обновление устаревшего Snapshot неуспешно из-за временной недоступности T-Bank, а в текущей границе подключения есть полный успешный Snapshot
|
||||
- **THEN** система отвечает `200` этим Snapshot с `isStale: true` и исходным `lastSuccessfulAt`
|
||||
|
||||
#### Scenario: Недействительный token не маскируется fallback-данными
|
||||
@@ -118,7 +127,14 @@ Portfolio Snapshot является результатом наблюдения
|
||||
|
||||
Клиент SHALL загружать Portfolio при открытии защищённого маршрута
|
||||
`/accounts/:accountId`. Он MUST использовать успешный ответ в течение
|
||||
30 секунд, без automatic retry, polling или refetch при возврате фокуса.
|
||||
30 секунд, без automatic retry или refetch при возврате фокуса.
|
||||
Polling допускается только для известной работы открытого экрана;
|
||||
data GET наблюдения использует `sync=observe` и MUST NOT запускать новый импорт.
|
||||
Status сообщает state/errorCode без hash notifications и численных progress counters.
|
||||
После ухода или завершения работы polling MUST прекращаться.
|
||||
|
||||
Предзагрузка всей истории свечей бумаг портфеля MUST NOT выполняться.
|
||||
Новый диапазон свечей загружается при его открытии; initial loading допустим.
|
||||
При загрузке без ранее полученного успешного ответа для этого же Brokerage
|
||||
Account клиент MUST показывать структурное skeleton-состояние ожидаемого
|
||||
содержимого, включая сводку, без вымышленных сумм. Область загрузки MUST
|
||||
|
||||
@@ -53,11 +53,21 @@
|
||||
|
||||
#### Scenario: Истёкшая сессия
|
||||
- **WHEN** клиент отправляет refresh-cookie Session, не обновлявшейся более 7 дней
|
||||
- **THEN** система удаляет refresh-cookie и отвечает `401` Problem Details с code `UNAUTHORIZED`
|
||||
- **THEN** система отвечает `401` Problem Details с code `UNAUTHORIZED`, не изменяя cookie неуспешным refresh
|
||||
|
||||
#### Scenario: Повторное использование refresh token
|
||||
- **WHEN** клиент отправляет refresh token, заменённый предыдущим успешным refresh
|
||||
- **THEN** система удаляет refresh-cookie и отвечает `401` Problem Details с code `UNAUTHORIZED`, не отзывая связанную Session только из-за этого запроса
|
||||
- **THEN** система отвечает `401` Problem Details с code `UNAUTHORIZED`, не изменяет cookie и не отзывает связанную Session только из-за этого запроса
|
||||
|
||||
### Requirement: Межвкладочная координация не требуется
|
||||
Frontend MUST сохранять изоляцию данных текущей identity внутри вкладки.
|
||||
Он MUST NOT требовать cross-tab synchronization для auth flow. После смены
|
||||
auth-состояния в другой вкладке допускаются reload или повторная авторизация.
|
||||
Неуспешный refresh MUST NOT удалять cookie успешного конкурентного запроса.
|
||||
|
||||
#### Scenario: Конкурентный refresh проигрывает в другой вкладке
|
||||
- **WHEN** вкладка получает `401` после ротации общей cookie другой вкладкой
|
||||
- **THEN** она может перейти на login; cookie победителя остаётся доступной для последующего восстановления
|
||||
|
||||
### Requirement: Завершение сессии
|
||||
Система SHALL позволять завершить текущую Session через logout. Logout MUST отозвать Session, если refresh-cookie соответствует активной Session, и MUST удалить refresh-cookie. Logout MUST быть идемпотентным и не раскрывать существование Session.
|
||||
|
||||
Reference in New Issue
Block a user