docs(ai): route frontend conventions by task

This commit is contained in:
2026-09-09 16:22:47 +03:00
parent 26f229ba3e
commit bcc034f198
14 changed files with 333 additions and 210 deletions
+56
View File
@@ -0,0 +1,56 @@
# 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/features/authentication.md).
Успешная connection mutation коммитит подтверждённый status и сбрасывает financial
GET subtree; ошибка mutation не меняет generation/cache. Это отдельная граница
от обычного фонового refetch: [connection policy](../../../docs/features/tbank-connection.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.