# Frontend data ## Выбор owner Server state принадлежит TanStack Query, form state — React Hook Form, локальное UI — React state. Не копируй успешный query result в useState/context для второго кэша. Domain-specific queries, keys и policies принадлежат вызывающему slice; общий transport — `shared/api`. Page VM выбирает inputs и собирает presentation data. Используй `apiClient`/`apiQueryClient` из shared public API. Прямой fetch в pages/features/entities и прямой T-Bank call запрещены. Сначала найди существующий query того же endpoint; расширяй его owner, не создавай второй key или глобальную query policy для одной страницы. ## Типы и contract Backend runtime OpenAPI — source; committed frontend snapshot и generated `schema.d.ts` производны. Тип request/response бери из generated `paths`, например: ```ts type User = paths["/api/v1/auth/me"]["get"]["responses"][200]["content"]["application/json"]; ``` Domain/UI type допустим, когда он отличается по смыслу, а не копирует transport DTO. Generated TS вручную не исправляется. Изменение wire shape/status/route проходит [общий contract workflow](../../../docs/development/runtime-openapi-verification.md). Одна UI-модель не требует менять API. `openapi:generate` работает offline от snapshot; `openapi:check` генерирует во временный каталог и сравнивает, не меняя tracked files. ## Auth и invalidation Bearer header принадлежит shared authenticated fetch; query/mutation не задают Authorization. Auth endpoints исключены из Bearer/retry middleware. Refresh координируется single-flight; после `401` с `UNAUTHORIZED` возможен один retry. Не добавляй собственный refresh/retry loop в caller. Protected queries используют existing session-aware boundary; logout очищает session-scoped cache. При auth/token change читай [security](../../../backend/.ai/conventions/security-auth.md) и [authentication](../../../docs/domains/authentication/overview.md). Успешная connection mutation коммитит подтверждённый status и сбрасывает financial GET subtree; ошибка mutation не меняет generation/cache. Это отдельная граница от обычного фонового refetch: [connection policy](../../../docs/integrations/tbank.md#граница-финансового-кэша). Default focus refetch выключен; freshness и retry определяются существующей [query policy](../../../docs/adr/007-react-query-fetch-policy.md) и feature source. При обычном refetch сохраняй Client Cached Snapshot, при session/connection смене не показывай данные прежнего владельца. UI presentation — в UI convention. ## Примеры и проверка [usePortfolio](../../src/entities/portfolio/api/usePortfolio.ts) — entity query; [shared client](../../src/shared/api/client.ts) — transport/auth boundary. Изменяя header/retry/invalidation, проверяй наблюдаемое поведение через MSW и [Testing](frontend-testing.md); не обращайся к реальному T-Bank. `npm run openapi:check`, `npm run typecheck` и targeted tests проверяют разные части решения. Для API semantics нужны также exact docs и contract gate.