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
|
### 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: Каждая выплата показана отдельной карточкой
|
#### Scenario: Каждая выплата показана отдельной карточкой
|
||||||
|
|
||||||
|
|||||||
@@ -94,20 +94,29 @@ Portfolio Snapshot является результатом наблюдения
|
|||||||
- **THEN** система передаёт её как строку `"-0.5"`
|
- **THEN** система передаёт её как строку `"-0.5"`
|
||||||
|
|
||||||
### Requirement: Свежесть и fallback полного Portfolio Snapshot
|
### 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
|
#### Scenario: Свежий Snapshot
|
||||||
- **WHEN** User повторно запрашивает тот же Portfolio в течение 30 секунд после успешного получения
|
- **WHEN** User повторно запрашивает тот же Portfolio в течение 60 секунд после успешного получения
|
||||||
- **THEN** система возвращает свежий Snapshot без нового обращения к T-Bank
|
- **THEN** система возвращает свежий Snapshot без нового обращения к T-Bank
|
||||||
|
|
||||||
#### Scenario: Медленный lookup инструмента
|
#### Scenario: Медленный lookup инструмента
|
||||||
- **WHEN** metadata инструмента ещё отсутствует и его lookup не завершился
|
- **WHEN** metadata инструмента ещё отсутствует и его lookup не завершился
|
||||||
- **THEN** система ожидает lookup в пределах gRPC deadline и возвращает name при успешном ответе upstream
|
- **THEN** система не задерживает локальный ответ ради lookup и показывает доступную identity; сохранённая успешная metadata используется последующим чтением
|
||||||
|
|
||||||
#### Scenario: Fallback после временной upstream-ошибки
|
#### Scenario: Fallback после временной upstream-ошибки
|
||||||
- **WHEN** обновление устаревшего Snapshot неуспешно из-за временной недоступности T-Bank, а последний полный успешный Snapshot получен не более пяти минут назад
|
- **WHEN** обновление устаревшего Snapshot неуспешно из-за временной недоступности T-Bank, а в текущей границе подключения есть полный успешный Snapshot
|
||||||
- **THEN** система отвечает `200` этим Snapshot с `isStale: true` и исходным `lastSuccessfulAt`
|
- **THEN** система отвечает `200` этим Snapshot с `isStale: true` и исходным `lastSuccessfulAt`
|
||||||
|
|
||||||
#### Scenario: Недействительный token не маскируется fallback-данными
|
#### Scenario: Недействительный token не маскируется fallback-данными
|
||||||
@@ -118,7 +127,14 @@ Portfolio Snapshot является результатом наблюдения
|
|||||||
|
|
||||||
Клиент SHALL загружать Portfolio при открытии защищённого маршрута
|
Клиент SHALL загружать Portfolio при открытии защищённого маршрута
|
||||||
`/accounts/:accountId`. Он MUST использовать успешный ответ в течение
|
`/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
|
При загрузке без ранее полученного успешного ответа для этого же Brokerage
|
||||||
Account клиент MUST показывать структурное skeleton-состояние ожидаемого
|
Account клиент MUST показывать структурное skeleton-состояние ожидаемого
|
||||||
содержимого, включая сводку, без вымышленных сумм. Область загрузки MUST
|
содержимого, включая сводку, без вымышленных сумм. Область загрузки MUST
|
||||||
|
|||||||
@@ -53,11 +53,21 @@
|
|||||||
|
|
||||||
#### Scenario: Истёкшая сессия
|
#### Scenario: Истёкшая сессия
|
||||||
- **WHEN** клиент отправляет refresh-cookie Session, не обновлявшейся более 7 дней
|
- **WHEN** клиент отправляет refresh-cookie Session, не обновлявшейся более 7 дней
|
||||||
- **THEN** система удаляет refresh-cookie и отвечает `401` Problem Details с code `UNAUTHORIZED`
|
- **THEN** система отвечает `401` Problem Details с code `UNAUTHORIZED`, не изменяя cookie неуспешным refresh
|
||||||
|
|
||||||
#### Scenario: Повторное использование refresh token
|
#### Scenario: Повторное использование refresh token
|
||||||
- **WHEN** клиент отправляет refresh token, заменённый предыдущим успешным refresh
|
- **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: Завершение сессии
|
### Requirement: Завершение сессии
|
||||||
Система SHALL позволять завершить текущую Session через logout. Logout MUST отозвать Session, если refresh-cookie соответствует активной Session, и MUST удалить refresh-cookie. Logout MUST быть идемпотентным и не раскрывать существование Session.
|
Система SHALL позволять завершить текущую Session через logout. Logout MUST отозвать Session, если refresh-cookie соответствует активной Session, и MUST удалить refresh-cookie. Logout MUST быть идемпотентным и не раскрывать существование Session.
|
||||||
|
|||||||
Reference in New Issue
Block a user