docs(specs): archive api contract resilience remediation
This commit is contained in:
+2
@@ -0,0 +1,2 @@
|
|||||||
|
schema: spec-driven
|
||||||
|
created: 2026-08-23
|
||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
## Контекст
|
||||||
|
|
||||||
|
Мотивация изложена в `proposal.md`, а поведенческий contract — в delta specs.
|
||||||
|
Backend документирует `200` через OpenAPI decorators, но Nest использует
|
||||||
|
стандартный `201` для трёх auth `POST` handlers, поскольку их runtime status
|
||||||
|
не задан явно. Runtime OpenAPI verifier сравнивает два документа, поэтому не
|
||||||
|
может обнаружить это расхождение HTTP responses.
|
||||||
|
|
||||||
|
Во frontend Accounts и Account view models выбирают блокирующий loading/error
|
||||||
|
state до проверки cached query data. У auth provider два пути refresh:
|
||||||
|
cold start напрямую вызывает API без `catch`, а общий refresh может отклонить
|
||||||
|
Promise при повторе защищённого запроса.
|
||||||
|
|
||||||
|
## Цели и исключения
|
||||||
|
|
||||||
|
**Цели:**
|
||||||
|
|
||||||
|
- Согласовать фактические auth success responses, OpenAPI, snapshot и
|
||||||
|
generated types на `200` с детерминированным regression gate без Prisma или
|
||||||
|
базы данных.
|
||||||
|
- Отображать существующие данные Accounts и Portfolio во время refetch и после
|
||||||
|
его ошибки с доступным локализованным warning и retry action.
|
||||||
|
- Дать cold start и повтору защищённого запроса единый non-throwing результат
|
||||||
|
refresh, сохранив текущие serialization и защиту routes.
|
||||||
|
- Фиксировать active remediation и обновлять feature/development документацию
|
||||||
|
только фактически поставленным поведением.
|
||||||
|
|
||||||
|
**Исключения:**
|
||||||
|
|
||||||
|
- Исправлять Prisma migration/e2e infrastructure или создавать workspace-wide
|
||||||
|
verifier, отложенный как WL-P2-05 и WL-P2-13.
|
||||||
|
- Менять refresh-cookie attributes, token lifetime, session rotation,
|
||||||
|
unauthorised-error codes, auth routes, cache TTL, refetch triggers или
|
||||||
|
backend Portfolio fallback policy.
|
||||||
|
- Распространять Client Cached Snapshot на постраничные operations/events,
|
||||||
|
чьи cursor и filters могут определять иной result set.
|
||||||
|
|
||||||
|
## Решения
|
||||||
|
|
||||||
|
### Явно установить `200` для трёх auth handlers успешного ответа
|
||||||
|
|
||||||
|
Handlers register, login и refresh получают явный HTTP `200`, сохраняя
|
||||||
|
существующие `ApiOkResponse` и payload/cookie code. Frontend artifacts остаются
|
||||||
|
сгенерированными из backend document: запускается штатный sync workflow, а
|
||||||
|
artifact коммитится только если этот workflow создаёт изменение; ручное
|
||||||
|
редактирование generated schema запрещено.
|
||||||
|
|
||||||
|
Небольшой независимый от БД backend test проверяет status metadata каждого
|
||||||
|
handler. Он защищает decorator, управляющий реальным Nest output, пока
|
||||||
|
Prisma-backed e2e gate остаётся deferred. Существующие e2e assertions меняются
|
||||||
|
с `201` на `200`, но не являются terminal evidence до восстановления Prisma
|
||||||
|
bootstrap.
|
||||||
|
|
||||||
|
Отклонённые альтернативы: неявный `201` потребовал бы большего перехода
|
||||||
|
snapshot/types и противоречил бы согласованному единообразному contract;
|
||||||
|
опора только на runtime OpenAPI comparison повторила бы исходную blind spot.
|
||||||
|
|
||||||
|
### Определять представление refetch по наличию данных, а не `isFetching` или `isError`
|
||||||
|
|
||||||
|
Accounts и Account view models сначала определяют наличие Client Cached
|
||||||
|
Snapshot. Без данных они сохраняют текущие loading, error и empty views. При
|
||||||
|
наличии данных они возвращают loaded/empty presentation с опциональной
|
||||||
|
информацией об обновлении и его ошибке. Page components сначала отображают
|
||||||
|
данные, добавляют неблокирующий progress indicator во время fetch и передают
|
||||||
|
локализованное warning/retry action в loaded presentation после ошибки.
|
||||||
|
|
||||||
|
Account view сохраняет backend warning `Portfolio.isStale` отдельно от client
|
||||||
|
warning об ошибке refresh. Оба могут отображаться, когда независимо истинны.
|
||||||
|
Новая терминология документируется в `CONTEXT.md`; это не новое API field и
|
||||||
|
не интерпретация server freshness.
|
||||||
|
|
||||||
|
Отклонённые альтернативы: полный error/loading view после refetch скрывает уже
|
||||||
|
полезные финансовые данные; применение правила к operations/events могло бы
|
||||||
|
показать прошлую cursor/filter page как запрошенный результат.
|
||||||
|
|
||||||
|
### Сделать общий refresh возвращающим `false` при любом неуспешном исходе
|
||||||
|
|
||||||
|
Auth provider централизует успешное применение session и локальную очистку
|
||||||
|
session. Single-flight refresh function перехватывает transport rejection API,
|
||||||
|
а также no-data/HTTP failures, очищает token, profile и React Query cache и
|
||||||
|
возвращает `false`; она всегда освобождает in-flight Promise. Cold start
|
||||||
|
использует эту общую function и устанавливает `ready` в `finally`.
|
||||||
|
`authenticatedFetch` сохраняет existing one-retry behavior: при `false` он
|
||||||
|
возвращает исходный `401` после очистки, позволяя protected-route state
|
||||||
|
перенаправить на login.
|
||||||
|
|
||||||
|
Отклонённые альтернативы: перехват только mount effect оставляет 401 retry
|
||||||
|
path способным отклонить Promise; добавление третьего startup error state
|
||||||
|
меняет согласованный anonymous/login recovery flow.
|
||||||
|
|
||||||
|
## Риски и компромиссы
|
||||||
|
|
||||||
|
- [Metadata test не является HTTP e2e test] → WL-P2-05 остаётся deferred,
|
||||||
|
существующие e2e expectations обновляются, а реальное HTTP coverage станет
|
||||||
|
обязательным после выполнения Prisma trigger.
|
||||||
|
- [Ошибка refresh утрачивает in-memory session] → после cold start браузер не
|
||||||
|
имеет действительного access token; очистка state предотвращает неоднозначный
|
||||||
|
protected UI и следует существующему 401 recovery behavior.
|
||||||
|
- [Client warning и backend stale warning могут сосуществовать] → каждому
|
||||||
|
назначается отдельное localized message и проверяется их независимый render.
|
||||||
|
- [Generated sync может затронуть frontend artifacts] → он запускается явно
|
||||||
|
только после backend contract change, а итоговый diff проверяется до принятия.
|
||||||
|
|
||||||
|
## План изменений
|
||||||
|
|
||||||
|
1. Сначала добавить regression tests, затем сделать backend status явным и
|
||||||
|
обновить существующие e2e assertions, не заявляя, что deferred e2e gate
|
||||||
|
прошёл.
|
||||||
|
2. Обновить OpenAPI artifacts через штатную sync command, проверить
|
||||||
|
согласованность runtime document и generated client и оставить только
|
||||||
|
намеренный итоговый diff.
|
||||||
|
3. Добавить observable frontend tests для состояний refetch cached data и
|
||||||
|
ошибок refresh, затем отрефакторить view models, pages, localized copy и
|
||||||
|
auth provider до их прохождения.
|
||||||
|
4. Обновить feature docs и remediation registry, выполнить применимые
|
||||||
|
non-mutating gates и OpenSpec verification до archive.
|
||||||
|
|
||||||
|
Rollback затрагивает только код: отмена затронутых commits восстанавливает
|
||||||
|
предыдущий status/UX; data migration, dependency change и очистка persisted
|
||||||
|
state не нужны.
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
## Обоснование
|
||||||
|
|
||||||
|
Auth endpoints фактически отвечают `201`, хотя их runtime OpenAPI-документ,
|
||||||
|
зафиксированный frontend snapshot и сгенерированный client обещают `200`.
|
||||||
|
Одновременно frontend скрывает успешные данные во время фонового обновления и
|
||||||
|
допускает необработанное отклонение Promise при транспортной ошибке начального
|
||||||
|
или повторного refresh.
|
||||||
|
|
||||||
|
Это следующий рекомендуемый remediation change для WL-P2-04, WL-P2-07 и
|
||||||
|
WL-P2-08: предыдущие P1 и связанные query-identity инварианты уже закрыты, а
|
||||||
|
Prisma e2e остаётся честно deferred отдельным finding.
|
||||||
|
|
||||||
|
## Изменения
|
||||||
|
|
||||||
|
- Зафиксировать единый HTTP `200` contract успешного ответа для register,
|
||||||
|
login и refresh; согласовать Nest runtime, OpenAPI snapshot,
|
||||||
|
сгенерированные frontend types и регрессионные проверки, не меняя logout
|
||||||
|
`204`, error semantics или cookie/session policy.
|
||||||
|
- Ввести UX Client Cached Snapshot для списка Brokerage Accounts и Portfolio:
|
||||||
|
уже полученные данные остаются видимыми при фоновом обновлении и его ошибке,
|
||||||
|
а ошибка отображается неблокирующе с повторной попыткой.
|
||||||
|
- Нормализовать транспортную ошибку общего frontend refresh flow в
|
||||||
|
контролируемое неавторизованное состояние без необработанного отклонения
|
||||||
|
Promise; очистка in-memory session и query cache сохраняет существующий
|
||||||
|
protected-route flow.
|
||||||
|
- Обновить устойчивую документацию и audit remediation registry по мере
|
||||||
|
реализации; не представлять metadata regression test как восстановленный
|
||||||
|
Prisma HTTP e2e gate.
|
||||||
|
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
### Новые возможности
|
||||||
|
|
||||||
|
- `frontend-data-resilience`: поведение Client Cached Snapshot и
|
||||||
|
неблокирующих refresh states для Accounts и Portfolio.
|
||||||
|
|
||||||
|
### Изменённые возможности
|
||||||
|
|
||||||
|
- `user-authentication`: единый auth success status и контролируемое
|
||||||
|
frontend-поведение при транспортной ошибке refresh.
|
||||||
|
|
||||||
|
## Затрагиваемые области
|
||||||
|
|
||||||
|
- Backend: auth controller и независимый от БД status regression test; текущий
|
||||||
|
Prisma e2e gate не меняется.
|
||||||
|
- Frontend: auth model, Accounts/Account view models и их observable UI tests;
|
||||||
|
сгенерированные OpenAPI artifacts обновляются только штатным sync workflow при
|
||||||
|
необходимости.
|
||||||
|
- Specs/docs: delta specs, `CONTEXT.md`, feature/development documentation и
|
||||||
|
remediation registry. Новых runtime dependencies, T-Bank credentials,
|
||||||
|
persisted migrations и публичных routes не требуется.
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
## Purpose
|
||||||
|
|
||||||
|
Определяет, когда frontend сохраняет последний успешный ответ на экране и как
|
||||||
|
сообщает пользователю о неудачном фоновом обновлении без искажения доменных
|
||||||
|
состояний Portfolio.
|
||||||
|
|
||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio
|
||||||
|
Frontend MUST сохранять Client Cached Snapshot списка Brokerage Accounts или
|
||||||
|
Portfolio на экране, если для этого же набора данных уже был успешно получен
|
||||||
|
ответ. Начальная загрузка без такого ответа может показывать блокирующее
|
||||||
|
состояние загрузки. Client Cached Snapshot MUST оставаться видимым во время
|
||||||
|
фонового обновления и после его ошибки; он не является server-side fallback и MUST NOT
|
||||||
|
изменять или интерпретировать поле `Portfolio.isStale`.
|
||||||
|
|
||||||
|
#### Scenario: Список Brokerage Accounts обновляется в фоне
|
||||||
|
- **WHEN** экран Accounts уже показывает Client Cached Snapshot и начинается
|
||||||
|
фоновое обновление того же списка
|
||||||
|
- **THEN** frontend оставляет список видимым и показывает только
|
||||||
|
неблокирующий индикатор обновления
|
||||||
|
|
||||||
|
#### Scenario: Обновление Portfolio завершается ошибкой после успешного ответа
|
||||||
|
- **WHEN** экран Brokerage Account уже показывает Client Cached Snapshot
|
||||||
|
Portfolio, а последующее обновление этого же Portfolio завершается ошибкой
|
||||||
|
- **THEN** frontend сохраняет Portfolio видимым, показывает локализованное
|
||||||
|
неблокирующее предупреждение о показе последних полученных данных и
|
||||||
|
предоставляет повторную попытку обновления
|
||||||
|
|
||||||
|
#### Scenario: Server-side fallback и client cached snapshot различаются
|
||||||
|
- **WHEN** backend возвращает Portfolio с `isStale` либо фоновое обновление
|
||||||
|
Client Cached Snapshot завершается ошибкой
|
||||||
|
- **THEN** frontend отображает соответствующее server-side либо client-side
|
||||||
|
предупреждение независимо, не представляя один вид состояния другим
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Единый HTTP contract успешных auth endpoints
|
||||||
|
Успешные `POST /api/v1/auth/register`, `POST /api/v1/auth/login` и
|
||||||
|
`POST /api/v1/auth/refresh` MUST отвечать HTTP `200`; опубликованный
|
||||||
|
OpenAPI-документ, зафиксированный frontend snapshot и сгенерированные
|
||||||
|
transport types MUST описывать этот же status. Каждая операция сохраняет свои
|
||||||
|
существующие payload, refresh-cookie и session semantics. Logout MUST
|
||||||
|
продолжать отвечать `204`.
|
||||||
|
|
||||||
|
#### Scenario: Успешная регистрация возвращает контрактный status
|
||||||
|
- **WHEN** пользователь отправляет новую валидную регистрацию
|
||||||
|
- **THEN** система устанавливает refresh-cookie, возвращает профиль и access
|
||||||
|
token с HTTP `200`
|
||||||
|
|
||||||
|
#### Scenario: Успешный login или refresh возвращает контрактный status
|
||||||
|
- **WHEN** пользователь успешно входит либо восстанавливает Session
|
||||||
|
- **THEN** система устанавливает или заменяет refresh-cookie, возвращает
|
||||||
|
профиль и access token с HTTP `200`
|
||||||
|
|
||||||
|
### Requirement: Клиент контролируемо завершает неуспешный refresh
|
||||||
|
Frontend MUST обрабатывать HTTP и транспортную ошибку общего refresh flow без
|
||||||
|
необработанного отклонения Promise. При неуспешном cold-start refresh frontend
|
||||||
|
MUST завершить инициализацию как неавторизованный, не сохраняя access token
|
||||||
|
или профиль. При неуспешном refresh после защищённого запроса frontend MUST
|
||||||
|
очистить in-memory session и query cache перед existing navigation to login.
|
||||||
|
|
||||||
|
#### Scenario: Cold-start refresh завершается транспортной ошибкой
|
||||||
|
- **WHEN** приложение запускается без access token и refresh запрос не может
|
||||||
|
получить транспортный response
|
||||||
|
- **THEN** frontend завершается в готовом неавторизованном состоянии без
|
||||||
|
необработанного отклонения Promise и показывает обычный public/login flow
|
||||||
|
|
||||||
|
#### Scenario: Повторный refresh после protected 401 завершается транспортной ошибкой
|
||||||
|
- **WHEN** защищённый API отвечает `401`, а единственный serialised refresh
|
||||||
|
завершается транспортной ошибкой
|
||||||
|
- **THEN** frontend очищает in-memory session и query cache и направляет User
|
||||||
|
в существующий login flow без необработанного отклонения Promise
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
## 1. Auth success-status contract
|
||||||
|
|
||||||
|
- [x] 1.1 Добавить независимый от БД backend regression test, который читает
|
||||||
|
Nest response-status metadata для `register`, `login` и `refresh` и
|
||||||
|
проверяет `200`; cookie/payload behavior не входит в его scope.
|
||||||
|
- [x] 1.2 Добавить явный runtime status `200` в три auth POST handlers, не
|
||||||
|
меняя logout `204`, error responses и session/cookie logic; добиться
|
||||||
|
прохождения нового metadata regression test.
|
||||||
|
- [x] 1.3 Обновить существующие auth e2e success expectations с `201` на
|
||||||
|
`200`, включая явный successful login assertion; задокументировать, что
|
||||||
|
suite остаётся deferred по WL-P2-05, а не считается passing gate.
|
||||||
|
- [x] 1.4 Запустить штатный frontend OpenAPI sync workflow после backend
|
||||||
|
change; принять только artifacts, сгенерированные этим workflow, затем
|
||||||
|
выполнить generated-artifact и runtime-contract checks.
|
||||||
|
|
||||||
|
## 2. Представление Client Cached Snapshot
|
||||||
|
|
||||||
|
- [x] 2.1 Добавить observable Accounts page regression coverage для
|
||||||
|
существующего списка во время in-flight refetch и после его ошибки: список
|
||||||
|
остаётся видимым, loading indicator неблокирующий, а retry локализованного
|
||||||
|
warning вновь вызывает тот же query.
|
||||||
|
- [x] 2.2 Расширить Account page coverage для эквивалентных Portfolio refetch
|
||||||
|
states, включая независимый render server `isStale` и client warnings об
|
||||||
|
ошибке refresh.
|
||||||
|
- [x] 2.3 Отрефакторить Accounts и Account view models, чтобы blocking
|
||||||
|
loading/error states выбирались только при отсутствии query data; раскрыть
|
||||||
|
progress, failure и retry refresh рядом с данными Client Cached Snapshot без
|
||||||
|
изменения query TTL, retry или refetch policies.
|
||||||
|
- [x] 2.4 Обновить Accounts и Account page presentations и localized copy для
|
||||||
|
отображения неблокирующего progress и доступных client refresh warnings с
|
||||||
|
retry, сохранив operations/events pagination вне scope.
|
||||||
|
|
||||||
|
## 3. Контролируемая ошибка refresh
|
||||||
|
|
||||||
|
- [x] 3.1 Добавить AuthProvider regression coverage для отклонённого
|
||||||
|
cold-start refresh: он устанавливает `ready`, оставляет user/access token
|
||||||
|
пустыми, очищает query cache и не создаёт необработанного отклонения Promise.
|
||||||
|
- [x] 3.2 Добавить coverage для protected `401`, чей serialised refresh имеет
|
||||||
|
транспортную ошибку: refresh возвращает контролируемую ошибку, локальный
|
||||||
|
auth/cache очищен, а исходный unauthorized response сохранён для
|
||||||
|
существующего route handling.
|
||||||
|
- [x] 3.3 Централизовать применение и очистку local auth state, направить
|
||||||
|
cold start и refresh защищённого запроса через общий non-throwing refresh
|
||||||
|
path и сохранить one-refresh-at-a-time behavior.
|
||||||
|
|
||||||
|
## 4. Устойчивая документация и состояние remediation
|
||||||
|
|
||||||
|
- [x] 4.1 Обновить feature documentation authentication, brokerage accounts и
|
||||||
|
portfolio с фактически поставленными `200` auth responses и различием между
|
||||||
|
server-side Portfolio fallback и Client Cached Snapshot refresh UX; limits и
|
||||||
|
deferred Prisma evidence должны остаться точными.
|
||||||
|
- [x] 4.2 Поддерживать `docs/development/audit-remediation.md` согласованным с
|
||||||
|
active status change и verification evidence; только после успешного archive
|
||||||
|
записать terminal archive path, commits и checks, затем отметить WL-P2-04,
|
||||||
|
WL-P2-07 и WL-P2-08 `done` вне этого task list.
|
||||||
|
|
||||||
|
## 5. Верификация перед archive
|
||||||
|
|
||||||
|
- [x] 5.1 Выполнить затронутые frontend и backend non-mutating lint, typecheck
|
||||||
|
и unit-test gates под Node 22; выполнить frontend `verify`, когда его
|
||||||
|
generated artifacts окончательны, и записать точные observed results.
|
||||||
|
- [x] 5.2 Выполнить `bash specs/scripts/verify-runtime-openapi.sh`, OpenSpec
|
||||||
|
authority verifier, strict change/spec validation и `git diff --check` в
|
||||||
|
каждом затронутом Git repository; устранить каждый blocking result.
|
||||||
|
- [x] 5.3 Провести независимый read-only review implementation, delta specs,
|
||||||
|
generated-contract diff, error-state tests и документации; выполнить
|
||||||
|
применимую `opsx-verify` procedure и устранить все blocking findings до
|
||||||
|
archive.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# frontend-data-resilience Specification
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Определяет, когда frontend сохраняет последний успешный ответ на экране и как
|
||||||
|
сообщает пользователю о неудачном фоновом обновлении без искажения доменных
|
||||||
|
состояний Portfolio.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio
|
||||||
|
Frontend MUST сохранять Client Cached Snapshot списка Brokerage Accounts или
|
||||||
|
Portfolio на экране, если для этого же набора данных уже был успешно получен
|
||||||
|
ответ. Начальная загрузка без такого ответа может показывать блокирующее
|
||||||
|
состояние загрузки. Client Cached Snapshot MUST оставаться видимым во время
|
||||||
|
фонового обновления и после его ошибки; он не является server-side fallback и MUST NOT
|
||||||
|
изменять или интерпретировать поле `Portfolio.isStale`.
|
||||||
|
|
||||||
|
#### Scenario: Список Brokerage Accounts обновляется в фоне
|
||||||
|
- **WHEN** экран Accounts уже показывает Client Cached Snapshot и начинается
|
||||||
|
фоновое обновление того же списка
|
||||||
|
- **THEN** frontend оставляет список видимым и показывает только
|
||||||
|
неблокирующий индикатор обновления
|
||||||
|
|
||||||
|
#### Scenario: Обновление Portfolio завершается ошибкой после успешного ответа
|
||||||
|
- **WHEN** экран Brokerage Account уже показывает Client Cached Snapshot
|
||||||
|
Portfolio, а последующее обновление этого же Portfolio завершается ошибкой
|
||||||
|
- **THEN** frontend сохраняет Portfolio видимым, показывает локализованное
|
||||||
|
неблокирующее предупреждение о показе последних полученных данных и
|
||||||
|
предоставляет повторную попытку обновления
|
||||||
|
|
||||||
|
#### Scenario: Server-side fallback и client cached snapshot различаются
|
||||||
|
- **WHEN** backend возвращает Portfolio с `isStale` либо фоновое обновление
|
||||||
|
Client Cached Snapshot завершается ошибкой
|
||||||
|
- **THEN** frontend отображает соответствующее server-side либо client-side
|
||||||
|
предупреждение независимо, не представляя один вид состояния другим
|
||||||
@@ -123,3 +123,40 @@
|
|||||||
#### Scenario: Выход из настроек
|
#### Scenario: Выход из настроек
|
||||||
- **WHEN** пользователь нажимает logout на `/settings`
|
- **WHEN** пользователь нажимает logout на `/settings`
|
||||||
- **THEN** клиент очищает локальную сессию и cache и направляет пользователя на `/login` независимо от результата сетевого запроса
|
- **THEN** клиент очищает локальную сессию и cache и направляет пользователя на `/login` независимо от результата сетевого запроса
|
||||||
|
|
||||||
|
### Requirement: Единый HTTP contract успешных auth endpoints
|
||||||
|
Успешные `POST /api/v1/auth/register`, `POST /api/v1/auth/login` и
|
||||||
|
`POST /api/v1/auth/refresh` MUST отвечать HTTP `200`; опубликованный
|
||||||
|
OpenAPI-документ, зафиксированный frontend snapshot и сгенерированные
|
||||||
|
transport types MUST описывать этот же status. Каждая операция сохраняет свои
|
||||||
|
существующие payload, refresh-cookie и session semantics. Logout MUST
|
||||||
|
продолжать отвечать `204`.
|
||||||
|
|
||||||
|
#### Scenario: Успешная регистрация возвращает контрактный status
|
||||||
|
- **WHEN** пользователь отправляет новую валидную регистрацию
|
||||||
|
- **THEN** система устанавливает refresh-cookie, возвращает профиль и access
|
||||||
|
token с HTTP `200`
|
||||||
|
|
||||||
|
#### Scenario: Успешный login или refresh возвращает контрактный status
|
||||||
|
- **WHEN** пользователь успешно входит либо восстанавливает Session
|
||||||
|
- **THEN** система устанавливает или заменяет refresh-cookie, возвращает
|
||||||
|
профиль и access token с HTTP `200`
|
||||||
|
|
||||||
|
### Requirement: Клиент контролируемо завершает неуспешный refresh
|
||||||
|
Frontend MUST обрабатывать HTTP и транспортную ошибку общего refresh flow без
|
||||||
|
необработанного отклонения Promise. При неуспешном cold-start refresh frontend
|
||||||
|
MUST завершить инициализацию как неавторизованный, не сохраняя access token
|
||||||
|
или профиль. При неуспешном refresh после защищённого запроса frontend MUST
|
||||||
|
очистить in-memory session и query cache перед existing navigation to login.
|
||||||
|
|
||||||
|
#### Scenario: Cold-start refresh завершается транспортной ошибкой
|
||||||
|
- **WHEN** приложение запускается без access token и refresh запрос не может
|
||||||
|
получить транспортный response
|
||||||
|
- **THEN** frontend завершается в готовом неавторизованном состоянии без
|
||||||
|
необработанного отклонения Promise и показывает обычный public/login flow
|
||||||
|
|
||||||
|
#### Scenario: Повторный refresh после protected 401 завершается транспортной ошибкой
|
||||||
|
- **WHEN** защищённый API отвечает `401`, а единственный serialised refresh
|
||||||
|
завершается транспортной ошибкой
|
||||||
|
- **THEN** frontend очищает in-memory session и query cache и направляет User
|
||||||
|
в существующий login flow без необработанного отклонения Promise
|
||||||
|
|||||||
Reference in New Issue
Block a user