Files
2026-08-14 09:49:55 +03:00

12 KiB
Raw Permalink Blame History

Контекст

Frontend уже использует React, FSD, generated OpenAPI types и React Query, но получает OpenAPI непосредственно из работающего backend и вручную создаёт query/mutation hooks. Bearer header одновременно добавляется общим HTTP transport и передаётся отдельными вызовами. Локальная проверка состоит из разрозненных команд и не проверяет generated artifact, не изолирует API-тесты и не контролирует границы FSD-слоёв.

Причина изменения описана в proposal.md, а контрактные требования — в specs/api-contract-generation/spec.md.

Цели и нецели

Цели:

  • Сделать настройку frontend, генерацию API-контракта и локальную проверку воспроизводимыми без запущенного backend, кроме явной синхронизации контракта.
  • Централизовать типизированную интеграцию React Query и auth transport без изменения существующих пользовательских сценариев и семантики cache.
  • Создать чистый, проверяемый и ориентированный на агентов baseline разработки с API mocks только для тестов.
  • Зафиксировать реализованный workflow в документации frontend и постоянной документации проекта.

Нецели:

  • Не мигрируются routes, forms, state-views, view-model и ErrorBoundary; они относятся к align-frontend-ui-patterns.
  • Не добавляются Storybook, Playwright, browser MSW worker, mock-режим разработки и CI configuration.
  • Не меняются владение backend OpenAPI, API routes, authentication protocol и доменная терминология WealthLedger.

Решения

Воспроизводимый frontend baseline

Frontend будет объявлять Node 22 через .nvmrc и package.json#engines. Зависимости будут использовать точные версии, а lockfile будет перегенерирован. Toolchain перейдёт на совместимый baseline template, включая Mantine 9, строгие опции TypeScript, aliases Vite/TypeScript и tooling статического анализа.

Aliases будут одинаково определены в Vite и TypeScript. Существующие cross-slice imports будут использовать публичные API через index.ts; файлы внутри slice могут использовать относительные imports. dependency-cruiser будет проверять только направление FSD-слоёв, а использование public API останется документированным правилом review.

Точные версии выбраны вместо semver ranges, чтобы установки агентов и разработчиков воспроизводили один dependency graph. Собственный Node version checker отклонён: .nvmrc и engines сообщают ограничение без дополнительного пути к ошибке.

Генерация OpenAPI из snapshot

src/shared/api/spec/ будет хранить committed raw JSON snapshot из backend OpenAPI endpoint, а src/shared/api/generated/schema.d.ts останется committed generated artifact. Явная sync-команда получит endpoint, настроенный VITE_API_BASE_URL, провалидирует его генерацией и заменит оба artifacts только после успеха всех шагов. Временные файлы не позволят неудачному fetch или generation частично обновить контракт.

openapi:generate будет генерировать из committed snapshot. openapi:check независимо сгенерирует ожидаемую schema во временную директорию и сравнит её с committed artifact. Команда не обращается к backend, поэтому verify остаётся доступным offline.

Генерация напрямую из работающего backend отклонена, потому что обычные локальные проверки станут зависимы от его доступности. Преобразование snapshot в YAML отклонено, потому что сохранение опубликованного JSON исключает ненужную трансформацию.

Типизированная интеграция queries и auth boundary

Shared OpenAPI client остаётся единственной HTTP entry point. openapi-react-query будет получать из него типизированные React Query operations; существующие query keys, enabled, stale times, retry policies, invalidations и отображение ошибок сохранятся. API request и response types продолжат выводиться из generated paths, а не дублировать DTOs.

Реализация authenticated fetch становится единственным владельцем Bearer header. Она исключает auth endpoints, делает ровно один retry только после 401 с UNAUTHORIZED и успешного refresh, а при неудачном refresh очищает session state. Query и mutation calls больше не передают Authorization самостоятельно. Initial session restoration должен обновлять и React state, и token reference, используемый transport; logout и неудачный refresh очищают оба и cache QueryClient.

Ручная передача headers отклонена: она дублирует cross-cutting security concern и может разойтись с поведением transport. Замена refresh semantics на library interceptor отклонена, потому что существующие refresh single-flight и browser lock уже являются корректным product behavior.

MSW только для тестов и целевые regression tests

MSW будет запускаться только через Vitest setup и handlers для текущего WealthLedger API. Не будут добавлены service worker, команда dev:mock, mock build и application mock mode. Поэтому unit и hook tests смогут выполнять успешные и ошибочные API scenarios без backend.

Целевые transport tests проверят Bearer injection, исключение auth endpoints, один refresh/retry для UNAUTHORIZED, очистку session после неудачного refresh и авторизацию восстановленной session. Coverage формируется как report, но не получает числовой threshold до стабилизации UI patterns.

Browser mocking отклонён, потому что он создаёт незапрошенный второй application mode. Coverage threshold отклонён, потому что текущий baseline слишком мал для стабильной и содержательной цели.

Единый локальный quality gate и постоянная документация

npm run verify будет запускать OpenAPI drift detection, typecheck, Biome, unit tests, coverage reporting, Knip, dependency-cruiser и production build. Все проверки должны проходить без baseline suppressions или allowlists. Husky устанавливается через prepare; pre-commit форматирует staged files и запускает contract и dependency checks, а commit-msg проверяет Conventional Commits.

Frontend AGENTS.md остаётся коротким индексом «задача → документ». Его локальные docs описывают API workflow, test setup, structure и conventions. После реализации docs/development/ получит постоянное cross-repository описание frontend workflow: требуемую Node version, contract synchronization и quality-gate commands. Так знания о реализованном процессе не останутся только в frontend repository.

Запуск полного gate в каждом pre-commit hook отклонён, потому что tests и builds замедляют обычные commits; verify остаётся единственным явным полным gate. Storybook и e2e build steps исключены вместе с их tools.

Риски и компромиссы

  • [Обновления Mantine и совместимых зависимостей могут выявить несовместимости исходного кода] → Устранить все type, lint и build errors до принятия нового lockfile.
  • [Committed snapshot может отставать от backend] → Backend остаётся источником истины; явный sync обновляет snapshot, а локальная проверка гарантирует только внутреннюю согласованность.
  • [Централизация Bearer injection может сломать восстановленные sessions] → Синхронизировать token reference во время initial refresh и покрыть поведение transport tests.
  • [Static analyzers могут сообщить о существующем коде] → Исправить код или точно настроить tool до получения зелёного baseline; не скрывать findings временными waivers.
  • [Hooks запускаются не во всех окружениях разработчиков] → npm run verify остаётся независимо запускаемым и документированным completion gate.

План миграции

  1. Обновить и зафиксировать frontend toolchain, настроить aliases и static-analysis tools, привести текущий исходный код к новым checks.
  2. Добавить OpenAPI snapshot, sync/generate/check commands, затем проверить generated artifact из committed snapshot без доступа к backend.
  3. Мигрировать API queries и mutations на typed integration, централизовать Bearer handling и добавить transport regression coverage.
  4. Добавить MSW только для тестов, coverage reporting, git hooks и единый скрипт verify.
  5. Обновить frontend agent documentation и docs/development/ описанием реализованного workflow, затем запустить полный quality gate.

Изменение локально для frontend и может быть отменено откатом его frontend и documentation commits. Backend contract не меняется.