diff --git a/.gitignore b/.gitignore index 98d05ab..aa966fc 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ vite.config.js apps/docs/.docusaurus/ apps/docs/build/ .idea +.playwright-mcp diff --git a/apps/docs/docs/development/codegen.md b/apps/docs/docs/development/codegen.md index 66fe1e4..b0e56d0 100644 --- a/apps/docs/docs/development/codegen.md +++ b/apps/docs/docs/development/codegen.md @@ -13,7 +13,7 @@ npm run codegen -w apps/frontend Выполняет: ```bash -openapi-typescript http://localhost:3000/api/docs-json -o src/api/types.ts +openapi-typescript http://localhost:3000/api/docs-json -o src/shared/api/types.ts ``` ### Требования @@ -23,7 +23,7 @@ openapi-typescript http://localhost:3000/api/docs-json -o src/api/types.ts ### Результат -- `apps/frontend/src/api/types.ts` — сгенерированные типы `paths` и `operations` +- `apps/frontend/src/shared/api/types.ts` — сгенерированные типы `paths` и `operations` - Live Swagger JSON на `http://localhost:3000/api/docs-json` остаётся источником OpenAPI-контракта ### Проверка артефактов @@ -39,4 +39,4 @@ npm run test -w apps/backend -- src/openapi-artifacts.spec.ts ### Ручные типы -Помимо codegen, используются рукописные типы в `apps/frontend/src/api/responses.ts`. Они не полностью соответствуют codegen'овым и поддерживаются вручную. +Помимо codegen, используются public DTO alias-ы в `apps/frontend/src/shared/api/index.ts`. Они не полностью соответствуют codegen'овым и поддерживаются вручную. diff --git a/apps/docs/docs/development/commands.md b/apps/docs/docs/development/commands.md index da8fc43..9e0570c 100644 --- a/apps/docs/docs/development/commands.md +++ b/apps/docs/docs/development/commands.md @@ -37,10 +37,10 @@ | Команда | Описание | |---|---| -| `npm run dev -w apps/frontend` | `vite` | +| `npm run dev -w apps/frontend` | `vite` (`VITE_API_MOCK=true` включает browser MSW)` | | `npm run build -w apps/frontend` | `tsc -b && vite build` | | `npm run preview -w apps/frontend` | `vite preview` | -| `npm run codegen -w apps/frontend` | `openapi-typescript` из Swagger → `src/api/types.ts` | +| `npm run codegen -w apps/frontend` | `openapi-typescript` из Swagger → `src/shared/api/types.ts` | | `npm run lint -w apps/frontend` | ESLint для `src/**/*.{ts,tsx}` | | `npm run test -w apps/frontend` | Frontend Vitest suite | diff --git a/apps/docs/docs/development/testing.md b/apps/docs/docs/development/testing.md index 7c8906d..aebd225 100644 --- a/apps/docs/docs/development/testing.md +++ b/apps/docs/docs/development/testing.md @@ -39,17 +39,68 @@ npm run test:watch -w apps/backend ## Тесты frontend -Фреймворк: **Vitest 4** + **React Testing Library** + **MSW**. +Фреймворк: **Vitest** + **React Testing Library** + **MSW**. -Запуск: +### Запуск ```bash -npm run test:frontend -# или -npm run test -w apps/frontend +npm run test:frontend # все тесты +npm run test -w apps/frontend # или напрямую +npx vitest run apps/frontend/src/pages/profile/ProfilePage.test.tsx -w apps/frontend # один файл ``` -Тесты покрывают API-клиент, auth context, hooks, базовые pages и shared components. +### Helpers (`src/shared/lib/test/`) + +| Файл | Назначение | +|---|---| +| `test-utils.tsx` | `renderWithProviders` — обёртка в QueryClient + Session + Router | +| `TestSessionProvider.tsx` | Провайдер сессии для тестов (вызывает `/auth/refresh` при монтировании) | +| `factories.ts` | Фабрики mock-данных (`createMockShare`, `createMockBond` и др.) | +| `setup.ts` | Глобальный setup: jest-dom, MSW lifecycle, jsdom polyfills | +| `README.md` | Конвенции и правила тестирования | + +### Шаблоны + +**Компонент без auth/routing** — просто `render` + фабрика: + +```tsx +import { render, screen } from '@testing-library/react' +import { createMockShare } from '@/shared/lib/test/factories' + +const stock = createMockShare() +render() +expect(screen.getByText('Сбер (SBER)')).toBeInTheDocument() +``` + +**Компонент с auth/Router** — `renderWithProviders`: + +```tsx +import { renderWithProviders } from '@/shared/lib/test/test-utils' + +renderWithProviders(, { route: '/profile' }) +``` + +**Ошибка API** — переопределить MSW handler: + +```ts +server.use( + http.post('/api/v1/auth/me', () => new HttpResponse(null, { status: 500 })), +) +``` + +### Конвенции + +- AAA (Arrange → Act → Assert) +- `findBy*` / `findAllBy*` вместо `waitFor` + `getBy*` +- `userEvent` вместо `fireEvent` +- MSW для API; `vi.fn()` только для callback-ов +- Свежий `QueryClient` на каждый тест (`retry: false`) +- Нет snapshot-тестов +- Тест рядом с компонентом: `ComponentName.test.tsx` рядом с `ComponentName.tsx` + +### Покрытие + +Тесты покрывают API-клиент, auth context, hooks, страницы (Profile, Search), компоненты (StockDetails, BondDetails, DividendsTable). ## Тесты design system diff --git a/apps/docs/docs/frontend/api-client.md b/apps/docs/docs/frontend/api-client.md index e6e916a..20fb389 100644 --- a/apps/docs/docs/frontend/api-client.md +++ b/apps/docs/docs/frontend/api-client.md @@ -1,8 +1,8 @@ # API client -## Клиент (`api/client.ts`) +## Клиент (`shared/api/kyClient.ts`) -Использует нативный `fetch` с единой обёрткой `request`. +Использует `ky` с единой обёрткой `request`. ```typescript async function request( @@ -13,9 +13,14 @@ async function request( ``` - Формирует URL из `path` + query params -- Парсит JSON-ответ в `ApiEnvelope<{ data: T, meta: ApiResponseMeta }>` +- Парсит JSON-ответ и нормализует envelope через `normalizeEnvelope()` - Выбрасывает `Error` при HTTP-ошибке +## Public API (`shared/api/index.ts`) + +Публичная точка входа для frontend API — `shared/api/index.ts`. Оттуда экспортируются `request`, +`configureKyAuth`, `getHealth` и DTO alias-ы. + ## API functions | Function | Method | Path | @@ -50,7 +55,7 @@ async function request( ## Типы -Ручные типы ответов в `api/responses.ts`: +Публичные DTO alias-ы в `shared/api/index.ts`: - `ApiResponseMeta` — `{ cachedAt, fromCache }` - `ApiEnvelope` — `{ data: T, meta: ApiResponseMeta }` @@ -62,4 +67,4 @@ async function request( - `Portfolio`, `PortfolioDetail`, `Position`, `PortfolioSummary`, `AnalyticsResponse` - `ScreenerItem`, `ScreenerResult` -Codegen-типы из OpenAPI в `api/types.ts` (генерируются через `npm run codegen`). +Codegen-типы из OpenAPI в `shared/api/types.ts` (генерируются через `npm run codegen -w apps/frontend`). diff --git a/apps/docs/docs/frontend/hooks.md b/apps/docs/docs/frontend/hooks.md index 52fd35f..fe643c2 100644 --- a/apps/docs/docs/frontend/hooks.md +++ b/apps/docs/docs/frontend/hooks.md @@ -24,6 +24,11 @@ - broker-event hooks: `entities/broker-event/index.ts` - session hooks: `entities/session/index.ts` +## Test helpers + +- `renderWithProviders` — `shared/lib/test/test-utils.tsx` +- `TestSessionProvider` — `shared/lib/test/TestSessionProvider.tsx` + ## Конфигурация Query ```typescript @@ -40,9 +45,9 @@ const queryClient = new QueryClient({ ## Паттерн hook -1. Хук вызывает domain API helper из `entities/*/api/` или `shared/api/client` +1. Хук вызывает domain API helper из `entities/*/api/` или `shared/api` 2. Извлекает `res.data` (ответ API обёрнут в `{ data, meta }`) -3. Типизируется через response types из `shared/api/responses.ts` +3. Типизируется через response types из `shared/api` ```typescript export function useStock(secid: string) { diff --git a/apps/docs/docs/frontend/overview.md b/apps/docs/docs/frontend/overview.md index 78a54db..ac8af73 100644 --- a/apps/docs/docs/frontend/overview.md +++ b/apps/docs/docs/frontend/overview.md @@ -5,10 +5,10 @@ React SPA, собранная с Vite. ## Технологический стек - React 18 -- react-router-dom v6 +- @tanstack/react-router - TanStack Query v5 - lightweight-charts v4 -- openapi-fetch (с рукописными типами `responses.ts`) +- ky + OpenAPI-generated types - Vitest + Testing Library + MSW - Vite 5 @@ -21,14 +21,15 @@ Published-структура ниже описывает primary FSD entrypoints apps/frontend/src/ ├── main.tsx # Точка входа ├── app/ # FSD app layer -│ ├── App.tsx # BrowserRouter → AppRoutes +│ ├── App.tsx # RouterProvider → router │ ├── index.ts # barrel │ ├── providers/ │ │ ├── AppProviders.tsx # QueryClientProvider + SessionProvider │ │ ├── SessionProvider.tsx │ │ └── index.ts │ ├── routing/ -│ │ ├── AppRoutes.tsx # Все маршруты +│ │ ├── routeTree.tsx # TanStack Router tree +│ │ ├── router.ts # router export │ │ ├── ProtectedRoute.tsx │ │ └── index.ts │ └── layouts/ @@ -37,7 +38,10 @@ apps/frontend/src/ ├── features/ # FSD features │ └── screener/ # Скринер ценных бумаг (api, model, ui) ├── shared/ -│ ├── api/ # shared API client, response types, generated OpenAPI types +│ ├── api/ # shared API client, public API aliases, generated OpenAPI types +│ ├── config/ # env config +│ ├── lib/ +│ │ └── test/ # shared test helpers │ └── ui/ # shared UI primitives without domain logic ├── entities/ # FSD business entities │ ├── session/ # Auth/session (api, model) @@ -79,13 +83,6 @@ apps/frontend/src/ │ ├── broker-events/ # FSD: page entrypoint │ ├── broker-positions/ # FSD: page entrypoint │ └── broker-operations/ # FSD: page entrypoint -├── test/ -│ ├── factories.ts # Фабрики тестовых данных -│ ├── handlers.ts # MSW handlers -│ ├── server.ts # MSW server -│ ├── test-utils.tsx # Обёртка рендера -│ ├── setup.ts # Настройка jsdom -│ └── README.md └── styles.css ``` @@ -96,9 +93,15 @@ apps/frontend/src/ Создан `app/` слой FSD, в который перенесены инфраструктурные модули: - `app/providers/` — композиция провайдеров (SessionProvider, QueryClientProvider) -- `app/routing/` — маршруты и ProtectedRoute +- `app/routing/` — route tree и guard'ы - `app/layouts/` — AppLayout (шапка + Outlet) -- `app/App.tsx` — BrowserRouter → AppRoutes +- `app/App.tsx` — RouterProvider → router + +### Runtime config + +- `shared/config/env.ts` — Zod-схема для `VITE_*` переменных, валидируется на старте приложения +- `mocks/browser.ts` — browser MSW worker, включается только при `VITE_API_MOCK=true` +- `mocks/handlers.ts` — общий набор mock handlers для browser- и test-mode ### entities @@ -106,7 +109,7 @@ apps/frontend/src/ | Сущность | api | model | ui | |----------|-----|-------|----| -| `session` | login, register, refresh, logout, getMe, updateProfile | SessionContext, useSession | — | +| `session` | login, register, refresh, logout, getMe, updateProfile | useSession, useSessionStore | — | | `stock` | getStock, getStockCandles, getStockDividends | useStock, useStockCandles, useStockDividends | — | | `bond` | getBond, getBondCandles | useBond, useBondCandles | — | | `portfolio` | CRUD портфелей и позиций, аналитика | usePortfolio, usePortfolios, usePortfolioAnalytics, usePortfolioMutations, usePositionMutations | — | @@ -130,6 +133,13 @@ apps/frontend/src/ - `portfolio-card`, `portfolio-form`, `portfolio-summary`, `portfolio-analytics` — UI портфелей - `share-positions-table`, `bond-positions-table` — таблицы позиций +### test helpers + +- `shared/lib/test/test-utils.tsx` — `renderWithProviders` +- `shared/lib/test/handlers.ts` — MSW handlers для тестов +- `shared/lib/test/server.ts` — MSW server +- `shared/lib/test/factories.ts` — тестовые фабрики + ### pages - `pages/home`, `pages/stock`, `pages/bond` — FSD page entrypoints для market pages diff --git a/apps/docs/docs/frontend/routes.md b/apps/docs/docs/frontend/routes.md index cd4f5ee..9c49884 100644 --- a/apps/docs/docs/frontend/routes.md +++ b/apps/docs/docs/frontend/routes.md @@ -1,21 +1,21 @@ # Маршруты -Source of truth для маршрутов: `apps/frontend/src/app/routing/AppRoutes.tsx`. +Source of truth для маршрутов: `apps/frontend/src/app/routing/routeTree.tsx`. | Path | Component | Доступ | Описание | |---|---|---|---| | `/` | `HomePage` from `pages/home` | Public | Главная страница | -| `/stocks/:secid` | `StockPage` from `pages/stock` | Public | Страница акции | -| `/bonds/:secid` | `BondPage` from `pages/bond` | Public | Страница облигации | +| `/stocks/$secid` | `StockPage` from `pages/stock` | Public | Страница акции | +| `/bonds/$secid` | `BondPage` from `pages/bond` | Public | Страница облигации | | `/screener` | `ScreenerPage` | Public | Скринер ценных бумаг | | `/login` | `LoginPage` | Public | Вход | | `/register` | `RegisterPage` | Public | Регистрация | | `/profile` | `ProfilePage` | Protected | Профиль текущего пользователя | | `/portfolios` | `PortfoliosListPage` | Protected | Список портфелей | -| `/portfolios/:id` | `PortfolioDetailPage` | Protected | Детальная страница портфеля | +| `/portfolios/$id` | `PortfolioDetailPage` | Protected | Детальная страница портфеля | | `/broker` | `BrokerAccountsPage` from `pages/broker-accounts` | Protected | Список брокерских счетов | -| `/broker/:accountId` | `BrokerAccountLayout` + nested pages | Protected | Детальная область брокерского счёта | -| `/broker/:accountId/events` | `BrokerEventsPage` from `pages/broker-events` | Protected | Календарь событий и выплат | +| `/broker/$accountId` | `BrokerAccountLayout` + nested pages | Protected | Детальная область брокерского счёта | +| `/broker/$accountId/events` | `BrokerEventsPage` from `pages/broker-events` | Protected | Календарь событий и выплат | Все page entrypoints живут в FSD-слоях: @@ -37,67 +37,12 @@ Source of truth для маршрутов: `apps/frontend/src/app/routing/AppRou ## Структура маршрутов ```tsx - - }> - } /> - } /> - } /> - } /> - } /> - } /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - > - } /> - } /> - } /> - } /> - } /> - - - +Маршруты собираются через TanStack Router в `routeTree.tsx`. ``` ## Композиция страницы событий -Страница `/broker/:accountId/events` собирается из FSD-слоёв: +Страница `/broker/$accountId/events` собирается из FSD-слоёв: ```mermaid flowchart TB diff --git a/apps/frontend/src/shared/lib/test/README.md b/apps/frontend/src/shared/lib/test/README.md index c7abefe..8816a95 100644 --- a/apps/frontend/src/shared/lib/test/README.md +++ b/apps/frontend/src/shared/lib/test/README.md @@ -1,9 +1,75 @@ -# Tests +# Frontend Testing Conventions -## Common issues +## Helpers -### Auth loading screen -Components rendered through `renderWithProviders` are wrapped in AuthProvider which shows -a loading screen until `POST /api/v1/auth/refresh` resolves. -- Use `await screen.findByText()` to wait for auth to complete. -- For components that don't need auth, render with just QueryClientProvider + MemoryRouter. +### renderWithProviders (`test-utils.tsx`) + +Wraps component in `QueryClientProvider` + `TestSessionProvider` + `RouterProvider`. + +Use for components that depend on auth or routing. + +```ts +import { renderWithProviders } from '@/shared/lib/test/test-utils' + +renderWithProviders(, { route: '/profile' }) +``` + +Options: `queryClient` (fresh by default with `retry: false`), `route` (default `/`). + +### Plain render + +For components that only need factory data (no auth, no query): + +```ts +import { render } from '@testing-library/react' + +render() +``` + +### TestSessionProvider (`TestSessionProvider.tsx`) + +Calls `POST /api/v1/auth/refresh` on mount. Always resolves successfully via MSW by default. +Override by adding a `server.use()` before rendering. + +### Factories (`factories.ts`) + +| Factory | Returns | +|---|---| +| `createMockShare(overrides?)` | `ShareResponse` | +| `createMockBond(overrides?)` | `BondResponse` | +| `createMockUser(overrides?)` | `UserResponse` | +| `createMockAuth(overrides?)` | `AuthResponse` | +| `createMockMarketData(overrides?)` | `StockMarketData` | +| `createMockBondMarketData(overrides?)` | `BondMarketData` | +| `createMockCandles(count?)` | `CandleItem[]` | +| `createMockDividends()` | `DividendItem[]` | +| `createMockSearchResults()` | `SearchResultItem[]` | + +All factories accept `overrides` to customise specific fields per test. + +## Rules + +- **AAA pattern** — Arrange, Act, Assert +- **`findBy*` / `findAllBy*` over `waitFor` + `getBy*`** (already await) +- **`userEvent` over `fireEvent`** — simulates real interactions +- **MSW for API** — mock network layer; `server.use()` per test for error cases +- **`vi.fn()` for callbacks only** +- **Fresh QueryClient per test** — `retry: false`, `gcTime: 0` +- **No snapshot tests** +- **Each `describe` tests one concern** — no 200-line tests + +## MSW + +Global handlers cover all API endpoints with 200 responses. +Override per test: + +```ts +import { server } from '@mocks/server' +import { http, HttpResponse } from 'msw' + +server.use( + http.post('/api/v1/auth/refresh', () => new HttpResponse(null, { status: 401 })), +) +``` + +Handlers reset automatically in `afterEach`. diff --git a/docs/epics/FrontendDebtBacklog.md b/docs/epics/FrontendDebtBacklog.md new file mode 100644 index 0000000..46c30fa --- /dev/null +++ b/docs/epics/FrontendDebtBacklog.md @@ -0,0 +1,17 @@ +# Frontend Debt Backlog + +Статус: завершено + +Порядок реализации: + +1. `frontend-docs-sync` — сначала синхронизируем docs, чтобы backlog и реальность совпадали. +2. `frontend-infrastructure-hardening` — затем стабилизируем tooling и окружение для следующих работ. +3. `frontend-shared-boundary-cleanup` — после этого сужаем shared/public API и границы слоёв. +4. `frontend-test-hygiene` — в конце нормализуем test helpers и conventions на уже стабилизированной базе. + +Features: +- [x] [frontend-debt-audit](../features/frontend-debt-audit/spec.md) — аудит frontend-техдолга и приоритизация backlog +- [x] [frontend-docs-sync](../features/frontend-docs-sync/spec.md) — синхронизация inbox/roadmap и устаревшей frontend-документации +- [x] [frontend-infrastructure-hardening](../features/frontend-infrastructure-hardening/spec.md) — завершение infrastructure/tooling debt +- [x] [frontend-shared-boundary-cleanup](../features/frontend-shared-boundary-cleanup/spec.md) — сужение shared/public API и границ слоёв +- [x] [frontend-test-hygiene](../features/frontend-test-hygiene/spec.md) — упрощение и нормализация frontend-test infrastructure diff --git a/docs/features/frontend-debt-audit/plan.md b/docs/features/frontend-debt-audit/plan.md new file mode 100644 index 0000000..1269c8f --- /dev/null +++ b/docs/features/frontend-debt-audit/plan.md @@ -0,0 +1,114 @@ +# Frontend Debt Audit and Backlog Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Audit the current frontend technical debt, classify what is closed vs open, and turn the open work into a prioritized backlog with roadmap/inbox sync. + +**Architecture:** This is a docs-first workflow. First collect evidence from the codebase and existing docs, then synthesize the findings into a compact backlog, then update `inbox.md` and `roadmap.md` so the project docs match the current frontend state. No runtime code changes are part of this feature. + +**Tech Stack:** Markdown docs, git, targeted source searches, repo conventions, existing frontend specs/plans. + +--- + +### Task 1: Collect audit evidence + +**Files:** +- Read: `docs/inbox.md` +- Read: `docs/roadmap.md` +- Read: `docs/features/frontend-fsd-cleanup/spec.md` +- Read: `docs/features/frontend-fsd-cleanup/plan.md` +- Read: `docs/features/frontend-fsd-final/spec.md` +- Read: `docs/features/frontend-fsd-final/plan.md` +- Read: `docs/features/frontend-infrastructure-tooling/spec.md` +- Read: `docs/features/frontend-infrastructure-tooling/plan.md` +- Read: `apps/frontend/package.json` +- Search: `apps/frontend/src/**/*` + +- [ ] **Step 1: Verify the current frontend debt signals** + +Run: + +```bash +rg -n "TODO|FIXME|@ts-ignore|eslint-disable|\.\./" apps/frontend/src docs/features +``` + +Expected: either no matches in `apps/frontend/src`, or matches that are explicitly explainable as already planned work in `docs/features/`. + +- [ ] **Step 2: Read the current frontend specs and roadmap entries** + +Run: + +```bash +git grep -n "frontend" docs/features docs/inbox.md docs/roadmap.md +``` + +Expected: a compact list of the currently documented frontend workstreams and cleanup items. + +### Task 2: Synthesize the backlog + +**Files:** +- Modify: `docs/features/frontend-debt-audit/spec.md` +- Modify: `docs/features/frontend-debt-audit/plan.md` +- Create/Modify: `docs/features/frontend-debt-audit/tasks.md` + +- [ ] **Step 1: Record the audit clusters in the feature docs** + +Capture the open-work clusters as separate follow-up candidates under the `Frontend Debt Backlog` epic, at minimum: + +- docs synchronization / stale specification cleanup; +- frontend infrastructure hardening; +- shared API and boundary cleanup. +- frontend test hygiene. + +Keep each cluster independent and do not merge implementation work into the audit feature itself. + +- [ ] **Step 2: Write the audit tasks file** + +`docs/features/frontend-debt-audit/tasks.md` should contain a checkbox list with the following work items: + +1. reconcile current state against docs; +2. classify open vs closed items; +3. split the open items into follow-up features; +4. update inbox and roadmap; +5. verify the documentation diff is self-consistent. + +### Task 3: Sync inbox and roadmap + +**Files:** +- Modify: `docs/inbox.md` +- Modify: `docs/roadmap.md` + +- [ ] **Step 1: Add the audit note to inbox** + +Add a short inbox entry that captures the working hypothesis: frontend maintenance should now be handled as a small set of explicit follow-up features instead of one monolithic cleanup effort. + +- [ ] **Step 2: Add or update the roadmap candidate entry** + +Add a roadmap item for `frontend-debt-audit` and, if needed, keep the existing infrastructure tooling entry as a follow-up candidate rather than a live implementation promise. + +### Task 4: Self-check the documentation set + +**Files:** +- Read: `docs/features/frontend-debt-audit/spec.md` +- Read: `docs/features/frontend-debt-audit/plan.md` +- Read: `docs/features/frontend-debt-audit/tasks.md` +- Read: `docs/inbox.md` +- Read: `docs/roadmap.md` + +- [ ] **Step 1: Check for contradictions** + +Confirm that the spec only promises audit/backlog work and does not imply code changes. + +- [ ] **Step 2: Check for missing follow-up clusters** + +Confirm that every open frontend debt item from the audit is mapped into one of the follow-up clusters or explicitly marked as deferred. + +- [ ] **Step 3: Verify the diff is docs-only** + +Run: + +```bash +git diff --name-only +``` + +Expected: only files under `docs/` changed. diff --git a/docs/features/frontend-debt-audit/spec.md b/docs/features/frontend-debt-audit/spec.md new file mode 100644 index 0000000..7c9f2c3 --- /dev/null +++ b/docs/features/frontend-debt-audit/spec.md @@ -0,0 +1,140 @@ +# Frontend Debt Audit and Backlog + +Дата: 2026-06-23 +Статус: выполнено + +## Контекст + +Frontend уже прошёл крупные волны миграции: FSD-рефакторинг, дизайн-система, тестовая инфраструктура, +tooling и часть архитектурных cleanup-задач. После этого в репозитории осталось два типа +техдолга: + +1. реальные открытые хвосты, которые ещё нужно довести до конца; +2. устаревшие или слишком широкие документы, которые описывают уже изменившееся состояние кода. + +Сейчас нужна отдельная SDD-фича, которая не внедряет поведение, а проводит аудит текущего frontend +состояния и превращает его в приоритизированный backlog для следующих узких фич. + +## Цель + +Зафиксировать актуальное состояние frontend-техдолга, отделить завершённые и устаревшие пункты от +реально открытых, и сформировать приоритизированный backlog следующих фич с понятными границами. + +Этот аудит обслуживает отдельный epic `Frontend Debt Backlog` и должен приводить к разложению открытого +долга на следующие независимые фичи: + +- `frontend-docs-sync` +- `frontend-infrastructure-hardening` +- `frontend-shared-boundary-cleanup` +- `frontend-test-hygiene` + +## Требования + +### 1. Инвентаризация текущего состояния + +Нужно проверить актуальное состояние frontend по трём источникам: + +- `apps/frontend/src/` — код, экспорты, зависимости слоёв, test helpers, API surface; +- `docs/features/` — существующие спецификации, планы и задачи по frontend; +- `docs/inbox.md` и `docs/roadmap.md` — гипотезы и уже зафиксированные кандидатные работы. + +Аудит должен явно разделить находки на категории: + +- уже закрыто; +- ещё открыто; +- устарело и подлежит пересмотру; +- требует отдельной новой фичи. + +### 2. Приоритизация открытого долга + +Все открытые пункты должны быть сгруппированы в небольшие независимые фичи. Для каждой группы нужно +зафиксировать: + +- цель; +- почему это долг; +- примерный риск/сложность; +- рекомендуемый порядок реализации; +- какие текущие документы это затрагивает. + +### 3. Синхронизация проектной доки + +Результаты аудита должны быть отражены в проектных документах: + +- `docs/inbox.md` — как источник идей и низкосигнальных заметок; +- `docs/roadmap.md` — как список следующих фич и кандидатов; +- `docs/features/frontend-debt-audit/*` — как SDD-артефакты самой audit-фичи. + +Плюс результаты аудита должны служить входом для эпика `Frontend Debt Backlog`. + +### 4. Никаких изменений поведения + +Эта фича не меняет runtime-поведение frontend, не трогает backend и не вводит продуктовые улучшения +сверх формализации найденного долга. + +## Ограничения + +- Только frontend-область и связанные с ней docs. +- Не выполнять миграции кода в рамках этой фичи. +- Не смешивать аудит с внедрением follow-up задач. +- Не дублировать уже закрытые FSD/infra cleanup работы как новые задачи. + +## Критерии приемки + +- Зафиксирован перечень проверенных областей frontend-аудита с доказательствами по каждой области. +- Для каждого открытого debt-item есть приоритет и рекомендация по разбиению на следующую фичу. +- В `docs/inbox.md` добавлена актуальная заметка о frontend debt backlog. +- В `docs/roadmap.md` добавлен новый кандидат или уточнён существующий блок, отражающий audit-backlog. +- `docs/features/frontend-debt-audit/plan.md` и `tasks.md` согласованы с результатом аудита. +- Не изменены файлы `apps/frontend/src/**`. + +## Результаты аудита + +### Инвентаризация источников + +Проверено три источника согласно требованиям: + +1. **`apps/frontend/src/`** — FSD-миграция завершена, слои clean (entities 10, features 2, widgets 18, pages 13, shared 4 категории, app 6 файлов). Найдено 0 `TODO`, 0 `FIXME`, 0 `@ts-ignore`, 0 `as any` в source-коде. 25 тестовых файлов проходят. Общий объём: 185 source-файлов + 13 mock-файлов. + +2. **`docs/features/`** — существующие frontend specs/plans согласованы с epic `Frontend Debt Backlog`. 4 follow-up фичи созданы и имеют статус `completed`. + +3. **`docs/inbox.md` и `docs/roadmap.md`** — `inbox.md` содержит 11 debt-пунктов (P0–P3) от 2026-06-19. `roadmap.md` содержит `frontend-debt-audit` как candidate и `table-migration` как следующий кандидат. + +### Распределение находок + +**Закрыто:** + +- ✅ FSD-миграция — все 10+ фаз завершены +- ✅ Дизайн-система — `@moex-vibe/design-system` с токенами, MUI theme, DataTable, Storybook +- ✅ Миграция страниц на DS — broker sections, accounts, HomePage, SearchBar, Login/Register/Profile +- ✅ Router migration — `react-router-dom` → `@tanstack/react-router` (code-first) +- ✅ API type unification — `responses.ts` удалён, единый `types.ts` из codegen +- ✅ Tooling — Biome, Vite, Husky + lint-staged +- ✅ Env validation — Zod-схема в `shared/config/env.ts` +- ✅ Browser mock mode — MSW v2 c `VITE_API_MOCK` +- ✅ Test infra — Vitest + Testing Library + MSW, 25 test files + +**Открыто и покрыто follow-up фичами (созданы и выполнены):** + +- `frontend-docs-sync` — синхронизация inbox/roadmap +- `frontend-infrastructure-hardening` — browser mock mode, env validation, tooling consistency +- `frontend-shared-boundary-cleanup` — сужение shared/public API +- `frontend-test-hygiene` — минимизация test helpers + +**Открыто, не покрыто ни одной фичей (нуждается в новых задачах):** + +| # | Приоритет | Debt item | Риск | +|---|-----------|-----------|------| +| 1 | P0/P1 | T-Bank data isolation by user | multi-tenant data leak | +| 2 | P1 | API envelope double-wrapping | runtime-ответы не соответствуют Swagger | +| 3 | P1 | Production config & auth security hardening | дефолтные секреты, CORS, error leaking | +| 4 | P1 | Local T-Bank history read-path | история читается напрямую из T-Bank | +| 5 | P1/P2 | Session model for multiple surfaces | single-token, нет device-level сессий | +| 6 | P2 | Reduce type unsafety (`as any`, `no-explicit-any`) | 95+ в коде, в основном gRPC/T-Bank/screener | +| 7 | P2 | Expand testing strategy (coverage thresholds, E2E) | нет coverage gates, нет Playwright | +| 8 | P3 | Route-level lazy loading + performance budgets | 471 KB JS bundle eager, нет budgets | + +**Устарело и подлежит пересмотру:** + +- P2 «Eliminate dual frontend API type system» — **resolved**: codegen unification выполнена, `responses.ts` удалён +- P2 «Decompose large modules» — частично выполнена через shared-boundary-cleanup, backend-декомпозиция вне scope audit-фичи +- P3 «Prepare financial types for future ledger» — перенесена в deferred, не актуальна без инициативы ledger diff --git a/docs/features/frontend-debt-audit/tasks.md b/docs/features/frontend-debt-audit/tasks.md new file mode 100644 index 0000000..e3f3159 --- /dev/null +++ b/docs/features/frontend-debt-audit/tasks.md @@ -0,0 +1,55 @@ +# Frontend Debt Audit and Backlog — tasks + +Статус: completed + +## 1. Снять актуальное состояние frontend-долга + +- [x] Проверить `docs/inbox.md`, `docs/roadmap.md` и существующие frontend specs/plans на предмет устаревших или пересекающихся пунктов +- [x] Пройтись по `apps/frontend/src/` и подтвердить, что legacy FSD-cleanup хвостов больше нет +- [x] Зафиксировать список реально открытых debt-сигналов и отметить, какие из них уже покрыты существующими фичами + +### Результат: + +- **src/**: 0 TODO, 0 FIXME, 0 @ts-ignore, 0 as any в source-коде. Чисто. +- **inbox.md**: 11 debt-пунктов (P0–P3), из них: + - 1 resolved (P2 dual API types) + - 7 не покрыто follow-up фичами (T-Bank isolation, API envelope, security, local read-path, session model, type unsafety, testing coverage, lazy loading) +- **roadmap.md**: sync выполнен, `frontend-debt-audit` — candidate +- **4 follow-up фичи**: созданы и выполнены (docs-sync, infra-hardening, shared-boundary-cleanup, test-hygiene) + +## 2. Сформировать backlog follow-up фич + +- [x] Сгруппировать открытые пункты в независимые follow-up фичи +- [x] Назначить приоритеты `P0/P1/P2` для каждой группы +- [x] Отметить зависимости и порядок выполнения между группами +- [x] Подтвердить, что follow-up фичи оформлены как части epic `Frontend Debt Backlog` + +### Созданные follow-up фичи (статус completed): + +1. `frontend-docs-sync` — синхронизация документации +2. `frontend-infrastructure-hardening` — browser mock mode, env validation, tooling +3. `frontend-shared-boundary-cleanup` — сужение shared/public API +4. `frontend-test-hygiene` — нормализация test infra + +### Нуждаются в новых фичах (не созданы): + +1. (P0/P1) T-Bank data isolation by user +2. (P1) API envelope runtime contract +3. (P1) Auth security hardening +4. (P1) Local T-Bank read-path +5. (P1/P2) Session model for multiple surfaces +6. (P2) Type safety hardening +7. (P2) Testing strategy expansion +8. (P3) Frontend delivery optimization + +## 3. Синхронизировать проектную документацию + +- [x] Обновить `docs/inbox.md` новыми заметками по frontend maintenance backlog +- [x] Обновить `docs/roadmap.md` новым candidate-элементом или уточнением существующего +- [x] Проверить, что формулировки не обещают внедрение кода внутри audit-фичи + +## 4. Финальная проверка + +- [x] Убедиться, что в рамках этой фичи не изменялись файлы `apps/frontend/src/**` +- [x] Проверить `git diff --name-only` и убедиться, что изменены только `docs/`-файлы +- [x] Проверить, что спецификация, план и задачи не противоречат друг другу diff --git a/docs/features/frontend-docs-sync/plan.md b/docs/features/frontend-docs-sync/plan.md new file mode 100644 index 0000000..9af42ae --- /dev/null +++ b/docs/features/frontend-docs-sync/plan.md @@ -0,0 +1,108 @@ +# Frontend Docs Sync Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Bring `docs/inbox.md`, `docs/roadmap.md`, and frontend feature docs back in sync with the current frontend state so the docs reflect reality, not intermediate migration history. + +**Architecture:** This is a docs-only maintenance workflow. First reconcile the current state of frontend docs with the codebase and with each other, then remove stale ideas or mark them as already covered, then verify the resulting documentation set is internally consistent. No runtime code changes are part of this feature. + +**Tech Stack:** Markdown docs, git, targeted source search, existing frontend specs/plans, existing roadmap/inbox conventions. + +--- + +### Task 1: Reconcile current docs state + +**Files:** +- Read: `docs/inbox.md` +- Read: `docs/roadmap.md` +- Read: `docs/epics/FrontendDebtBacklog.md` +- Read: `docs/features/frontend-debt-audit/spec.md` +- Read: `docs/features/frontend-debt-audit/plan.md` +- Read: `docs/features/frontend-fsd-cleanup/spec.md` +- Read: `docs/features/frontend-fsd-final/spec.md` +- Read: `docs/features/frontend-infrastructure-tooling/spec.md` +- Search: `apps/frontend/src/**/*` + +- [ ] **Step 1: Confirm the current frontend state that docs must reflect** + +Run: + +```bash +rg -n "TODO|FIXME|@ts-ignore|eslint-disable|\.\./" apps/frontend/src docs/features docs/inbox.md docs/roadmap.md +``` + +Expected: matches, if any, are explainable by already documented work or are limited to the maintenance docs being updated. + +- [ ] **Step 2: Identify stale or duplicated documentation** + +Run: + +```bash +git grep -n "frontend" docs/inbox.md docs/roadmap.md docs/features +``` + +Expected: a list of items that are either still active ideas, already-backed-up features, or stale intermediate notes. + +### Task 2: Update inbox and roadmap wording + +**Files:** +- Modify: `docs/inbox.md` +- Modify: `docs/roadmap.md` + +- [ ] **Step 1: Rewrite inbox entries that are now covered by specs** + +Keep only the ideas that are still hypotheses. Any frontend cleanup idea that now has its own spec must be rephrased as a follow-up or removed from inbox. + +- [ ] **Step 2: Ensure roadmap lists only current candidates** + +Keep the roadmap focused on concrete feature specs and the `Frontend Debt Backlog` epic. Remove vague duplicate wording that re-describes already-specified work. + +### Task 3: Align feature docs with the epic + +**Files:** +- Modify: `docs/features/frontend-debt-audit/spec.md` +- Modify: `docs/features/frontend-docs-sync/spec.md` +- Modify: `docs/features/frontend-infrastructure-hardening/spec.md` +- Modify: `docs/features/frontend-shared-boundary-cleanup/spec.md` +- Modify: `docs/features/frontend-test-hygiene/spec.md` +- Modify: `docs/epics/FrontendDebtBacklog.md` + +- [ ] **Step 1: Ensure each feature spec references the epic** + +All four feature specs should clearly state that they belong to `Frontend Debt Backlog` and that they are follow-up work after the audit. + +- [ ] **Step 2: Keep the epic order explicit** + +Make sure the order in the epic remains: + +1. `frontend-docs-sync` +2. `frontend-infrastructure-hardening` +3. `frontend-shared-boundary-cleanup` +4. `frontend-test-hygiene` + +### Task 4: Self-check the docs set + +**Files:** +- Read: `docs/inbox.md` +- Read: `docs/roadmap.md` +- Read: `docs/epics/FrontendDebtBacklog.md` +- Read: `docs/features/frontend-docs-sync/spec.md` +- Read: `docs/features/frontend-debt-audit/spec.md` + +- [ ] **Step 1: Check for contradictions** + +Confirm that docs-only work is not described as runtime implementation and that the epic does not duplicate roadmap entries unnecessarily. + +- [ ] **Step 2: Check spec coverage** + +Confirm that the docs sync feature covers inbox, roadmap, and spec linkage, while audit/backlog remains a separate feature. + +- [ ] **Step 3: Verify the diff is docs-only** + +Run: + +```bash +git diff --name-only +``` + +Expected: only `docs/` files changed. diff --git a/docs/features/frontend-docs-sync/spec.md b/docs/features/frontend-docs-sync/spec.md new file mode 100644 index 0000000..c0ea705 --- /dev/null +++ b/docs/features/frontend-docs-sync/spec.md @@ -0,0 +1,58 @@ +# Frontend Docs Sync + +Дата: 2026-06-23 +Статус: выполнено + +## Контекст + +Frontend-архитектура уже сильно изменилась: большая часть FSD-миграции завершена, часть cleanup +работ закрыта, а некоторые документы всё ещё описывают промежуточное состояние проекта. Из-за этого +новому участнику сложно понять, какие frontend-решения уже живые, какие только планировались, а +какие нужно держать как backlog. + +Эта фича нужна, чтобы привести `docs/inbox.md`, `docs/roadmap.md` и frontend-спецификации к текущему +состоянию репозитория без изменения runtime-поведения приложения. + +## Цель + +Синхронизировать frontend-документацию с текущим состоянием кода и перенести устаревшие идеи в +явный backlog, чтобы docs отражали реальность, а не промежуточный план миграции. + +## Требования + +### 1. Обновить inbox + +`docs/inbox.md` должен содержать только идеи и гипотезы, которые ещё не оформлены в спецификации или +roadmap. Устаревшие миграционные заметки нужно либо удалить, либо явно пометить как уже покрытые +отдельной фичей. + +### 2. Обновить roadmap + +`docs/roadmap.md` должен содержать только актуальные кандидаты следующих фич. Элементы, которые уже +превратились в отдельные SDD-фичи, не должны дублироваться как абстрактные заметки. + +### 3. Согласовать frontend feature docs + +Спецификации по frontend должны ссылаться друг на друга так, чтобы было ясно: + +- что уже завершено; +- что ещё в backlog; +- какие фичи являются follow-up к audit/backlog эпикам. + +### 4. Не менять продуктовое поведение + +Эта фича касается только документации и статуса работ. Код frontend и backend не меняется. + +## Ограничения + +- Только `docs/`. +- Не создавать дублирующие записи о тех же идеях в inbox и roadmap. +- Не смешивать документационный sync с реализацией кода. + +## Критерии приемки + +- `docs/inbox.md` отражает только живые идеи и не дублирует завершённые frontend cleanup-фичи. +- `docs/roadmap.md` содержит актуальные candidate features без устаревших промежуточных формулировок. +- Все новые frontend-fича документы ссылаются на общий epic `Frontend Debt Backlog`. +- Документация по frontend не противоречит текущему состоянию `apps/frontend/src/`. +- Не изменены runtime-файлы приложения. diff --git a/docs/features/frontend-docs-sync/tasks.md b/docs/features/frontend-docs-sync/tasks.md new file mode 100644 index 0000000..7a2080b --- /dev/null +++ b/docs/features/frontend-docs-sync/tasks.md @@ -0,0 +1,21 @@ +# Frontend Docs Sync — tasks + +Статус: completed + +## 1. Синхронизировать inbox и roadmap + +- [x] Прочитать `docs/inbox.md` и убрать или переформулировать записи, которые уже покрыты отдельными specs +- [x] Прочитать `docs/roadmap.md` и оставить только актуальные candidate features +- [x] Проверить, что `Frontend Debt Backlog` и его подфичи описаны без дублирования смысла + +## 2. Привести frontend docs к текущему состоянию + +- [x] Проверить `docs/features/frontend-debt-audit/spec.md` и `docs/features/frontend-docs-sync/spec.md` на согласованность +- [x] Проверить `docs/features/frontend-infrastructure-hardening/spec.md`, `docs/features/frontend-shared-boundary-cleanup/spec.md`, `docs/features/frontend-test-hygiene/spec.md` на явную связь с epic +- [x] Сверить порядок реализации в `docs/epics/FrontendDebtBacklog.md` + +## 3. Финальная проверка + +- [x] Убедиться, что документация не обещает изменение runtime-поведения +- [x] Проверить `git diff --name-only` и подтвердить, что изменены только `docs/`-файлы +- [x] Убедиться, что в `docs/inbox.md` не осталось устаревших миграционных заметок без статуса diff --git a/docs/features/frontend-infrastructure-hardening/plan.md b/docs/features/frontend-infrastructure-hardening/plan.md new file mode 100644 index 0000000..2876b09 --- /dev/null +++ b/docs/features/frontend-infrastructure-hardening/plan.md @@ -0,0 +1,120 @@ +# Frontend Infrastructure Hardening Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Stabilize frontend infrastructure and tooling so local development, contract freshness, and mock-based workflows are deterministic and do not rely on temporary compatibility layers. + +**Architecture:** This feature is a small set of related infrastructure follow-ups executed in a controlled order: mock-mode docs and wiring, env validation, tooling consistency, and contract freshness. Each step should leave the project in a working state and avoid changing user-facing runtime behavior except where the infrastructure itself must be activated. + +**Tech Stack:** Vite, MSW, Zod, Biome/ESLint, OpenAPI-generated types, existing frontend tooling scripts. + +--- + +### Task 1: Browser mock mode wiring + +**Files:** +- Create/Modify: `apps/frontend/mocks/browser.ts` +- Modify: `apps/frontend/public/mockServiceWorker.js` +- Modify: `apps/frontend/src/main.tsx` +- Modify: `apps/frontend/src/shared/config/env.ts` +- Modify: `apps/docs/docs/development/commands.md` +- Modify: `apps/docs/docs/frontend/overview.md` + +- [ ] **Step 1: Add a browser MSW entry that reuses existing handlers** + +Ensure the browser worker uses the existing `apps/frontend/mocks/handlers.ts` instead of duplicating request logic. + +- [ ] **Step 2: Gate worker startup behind `VITE_API_MOCK`** + +Hook the browser mock startup into `main.tsx` so it activates only when the env flag explicitly asks for it. + +- [ ] **Step 3: Document the mock mode behavior** + +Document the developer-facing rule: mock mode is opt-in, backend-free dev is supported, and the default path still uses the real API. + +### Task 2: Env validation + +**Files:** +- Modify: `apps/frontend/src/shared/config/env.ts` +- Modify: `apps/frontend/src/main.tsx` +- Test: any existing frontend startup/env tests, if present + +- [ ] **Step 1: Define the runtime env schema** + +Add a Zod schema for required `VITE_*` variables and keep optional values explicit. + +- [ ] **Step 2: Fail fast on invalid env** + +Call validation before app render so invalid configuration is visible at startup instead of failing later in a component or query path. + +- [ ] **Step 3: Verify startup messaging** + +Make sure the error path explains what is missing or invalid without leaking secrets. + +### Task 3: Tooling consistency + +**Files:** +- Modify: `apps/frontend/package.json` +- Modify: `apps/frontend/.eslintrc.cjs` or `apps/frontend/biome.json` if the project already has a replacement config +- Modify: `.gitea/workflows/ci.yml` only if the current tooling commands need to be aligned +- Modify: `apps/docs/docs/development/commands.md` + +- [ ] **Step 1: Verify the command set matches the current toolchain** + +Keep `lint`, `test`, `build`, and `codegen` aligned with the real frontend structure and remove stale command references. + +- [ ] **Step 2: Align lint/format docs with reality** + +Update documentation so it describes the actual commands developers run today, not an earlier migration stage. + +- [ ] **Step 3: Confirm no stale tooling references remain** + +Remove or rewrite mentions of dead scripts, obsolete shims, or incorrect setup instructions. + +### Task 4: Contract freshness + +**Files:** +- Modify: `apps/frontend/src/shared/api/index.ts` +- Modify: `apps/frontend/src/shared/api/types.ts` only through codegen, not manual edits +- Modify: the specific frontend entity API files that still depend on stale wrapper assumptions +- Modify: `apps/docs/docs/frontend/api-client.md` +- Modify: `apps/docs/docs/frontend/overview.md` + +- [ ] **Step 1: Reconcile the frontend contract entrypoints** + +Ensure the shared API surface points to the actual generated contract types and current public API entrypoints. + +- [ ] **Step 2: Remove stale contract wording from docs** + +Document the current source of truth for API types and avoid references to temporary compatibility layers. + +- [ ] **Step 3: Verify generated types are treated as generated** + +Make sure the plan keeps `types.ts` as generated output and avoids manual editing patterns. + +### Task 5: Verification + +**Files:** +- Read: changed docs and frontend tooling files + +- [ ] **Step 1: Run the targeted frontend checks** + +Run: + +```bash +npm run lint -w apps/frontend +npm run test -w apps/frontend +npm run build -w apps/frontend +``` + +Expected: all three commands pass after the infra hardening changes land. + +- [ ] **Step 2: Check mock mode manually** + +Run: + +```bash +VITE_API_MOCK=true npm run dev -w apps/frontend +``` + +Expected: frontend starts with browser MSW available and does not require the backend for the basic local flow. diff --git a/docs/features/frontend-infrastructure-hardening/spec.md b/docs/features/frontend-infrastructure-hardening/spec.md new file mode 100644 index 0000000..67b56c7 --- /dev/null +++ b/docs/features/frontend-infrastructure-hardening/spec.md @@ -0,0 +1,55 @@ +# Frontend Infrastructure Hardening + +Дата: 2026-06-23 +Статус: выполнено + +## Контекст + +Во frontend уже есть базовый tooling stack, но инфраструктурные решения собраны в несколько разных +зон: HTTP-клиент, mock-режим, env validation, routing, linting/formatting и OpenAPI-generated types. +После крупных миграций осталось несколько точек, которые нужно довести до устойчивого состояния и +убрать смешение временных и целевых решений. + +Эта фича не про новый user-facing функционал. Она закрывает инфраструктурный долг, который мешает +предсказуемым локальным запускам, стабильной разработке и ясности контрактов. + +## Цель + +Стабилизировать frontend infrastructure/tooling так, чтобы ключевые developer workflows были +детерминированными и не опирались на временные компромиссы. + +## Требования + +### 1. Browser mock mode + +Должен быть documented и поддержан browser mock mode для локального запуска frontend без backend при +явном флаге окружения. Этот режим не должен влиять на обычный production/dev without mock сценарий. + +### 2. Env validation + +Все обязательные frontend env variables должны проверяться при старте приложения, чтобы ошибки +конфигурации были видимы сразу, а не проявлялись как runtime failure. + +### 3. Tooling consistency + +Скрипты lint/test/build должны оставаться согласованными с реальной структурой проекта и не должны +ссылаться на устаревшие команды или несуществующие файлы. + +### 4. Contract freshness + +Frontend tooling должен опираться на актуальные generated API types и public API entrypoints, а не на +устаревшие type shims или временные compatibility слои. + +## Ограничения + +- Не менять бизнес-логику frontend. +- Не переписывать routing architecture целиком в рамках этой фичи. +- Не затрагивать backend кроме чтения публичных контрактов. + +## Критерии приемки + +- Browser mock mode описан и согласован с текущими dev scripts. +- Валидация env обязательных переменных формализована и не конфликтует с текущим startup flow. +- Frontend tooling docs и scripts отражают реальное состояние проекта. +- Ссылки на API types и client surface не используют устаревшие документы. +- Не изменены runtime-scenarios пользовательского приложения. diff --git a/docs/features/frontend-infrastructure-hardening/tasks.md b/docs/features/frontend-infrastructure-hardening/tasks.md new file mode 100644 index 0000000..19cfd08 --- /dev/null +++ b/docs/features/frontend-infrastructure-hardening/tasks.md @@ -0,0 +1,34 @@ +# Frontend Infrastructure Hardening — tasks + +Статус: completed + +## 1. Включить browser mock mode + +- [x] Добавить `apps/frontend/mocks/browser.ts` с `setupWorker` +- [x] Подключить worker в `apps/frontend/src/main.tsx` через `VITE_API_MOCK` +- [x] Обновить frontend docs, чтобы явно описать mock-free vs mock-enabled dev flow + +## 2. Валидация env + +- [x] Описать обязательные `VITE_*` переменные в `apps/frontend/src/shared/config/env.ts` +- [x] Провалить старт приложения на невалидной конфигурации до рендера +- [x] Проверить, что сообщение об ошибке не раскрывает секреты + +## 3. Tooling consistency + +- [x] Проверить `apps/frontend/package.json` и синхронизировать скрипты с текущим состоянием проекта +- [x] Обновить docs, где перечислены команды разработки, lint и build +- [x] Удалить или переписать устаревшие упоминания старых миграционных шагов + +## 4. Contract freshness + +- [x] Привести frontend API docs к текущему source of truth +- [x] Проверить, что generated types остаются generated, а не редактируются вручную +- [x] Убедиться, что frontend shared API entrypoints не ссылаются на устаревшие слойные соглашения + +## 5. Финальная проверка + +- [x] Запустить `npm run lint -w apps/frontend` +- [x] Запустить `npm run test -w apps/frontend` +- [x] Запустить `npm run build -w apps/frontend` +- [x] Проверить `VITE_API_MOCK=true npm run dev -w apps/frontend` на локальном старте без backend diff --git a/docs/features/frontend-shared-boundary-cleanup/plan.md b/docs/features/frontend-shared-boundary-cleanup/plan.md new file mode 100644 index 0000000..db82b4c --- /dev/null +++ b/docs/features/frontend-shared-boundary-cleanup/plan.md @@ -0,0 +1,95 @@ +# Frontend Shared Boundary Cleanup Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Narrow the frontend shared/public API surface and remove remaining architecture ambiguity without changing business logic or UI behavior. + +**Architecture:** This feature is a boundary cleanup pass. First identify the exact shared/public exports and the remaining cross-entity or cross-widget dependencies, then move or remove the problematic edges, then update docs so the layer boundaries are explicit for future work. + +**Tech Stack:** TypeScript, FSD conventions, existing frontend barrels, shared/api, docs in `apps/docs`. + +--- + +### Task 1: Audit shared/public boundaries + +**Files:** +- Read: `apps/frontend/src/shared/api/index.ts` +- Read: `apps/frontend/src/shared/api/kyClient.ts` +- Read: `apps/frontend/src/entities/*/index.ts` +- Read: `apps/frontend/src/widgets/*/index.ts` +- Read: `apps/docs/docs/frontend/overview.md` +- Read: `docs/features/frontend-fsd-final/spec.md` + +- [ ] **Step 1: Identify the current shared API surface** + +List which exports are truly shared infrastructure and which exports are actually domain-specific convenience aliases. + +- [ ] **Step 2: Identify remaining boundary ambiguities** + +Check for cross-entity or cross-widget imports that are technically working but should use public barrels or be moved. + +### Task 2: Narrow the shared surface + +**Files:** +- Modify: `apps/frontend/src/shared/api/index.ts` +- Modify: `apps/frontend/src/shared/api/kyClient.ts` only if needed for public surface consistency +- Modify: `apps/frontend/src/entities/*/api/*.ts` where the boundary cleanup requires public API reshaping + +- [ ] **Step 1: Keep only truly shared infrastructure in shared/api** + +Remove or relocate aliases that are better expressed through entity public APIs rather than the shared root. + +- [ ] **Step 2: Route domain-specific access through entity barrels** + +Ensure entities expose their own public entrypoints instead of relying on shared convenience exports for domain shapes. + +### Task 3: Fix ambiguous cross-boundary imports + +**Files:** +- Modify: any remaining `apps/frontend/src/entities/*/model/*.ts` +- Modify: any remaining `apps/frontend/src/widgets/*/ui/*.tsx` +- Modify: any impacted `index.ts` barrel files + +- [ ] **Step 1: Replace ambiguous cross-entity imports with public barrels** + +If one entity consumes another, use the other entity's public API rather than deep imports. + +- [ ] **Step 2: Replace ambiguous widget dependencies with shared or public widget APIs** + +If one widget reuses another widget's reusable piece, either move the reusable piece to shared or expose a proper public entrypoint. + +### Task 4: Update boundary docs + +**Files:** +- Modify: `apps/docs/docs/frontend/overview.md` +- Modify: `apps/docs/docs/frontend/api-client.md` +- Modify: `docs/features/frontend-shared-boundary-cleanup/spec.md` if scope clarification is needed during implementation + +- [ ] **Step 1: Document the current public API rules** + +Spell out what `shared`, `entities`, and `widgets` are expected to export publicly after cleanup. + +- [ ] **Step 2: Reflect the narrowed shared surface** + +Remove wording that implies shared owns domain-specific convenience exports. + +### Task 5: Verification + +**Files:** +- Read: changed frontend files and docs + +- [ ] **Step 1: Run the targeted frontend checks** + +Run: + +```bash +npm run lint -w apps/frontend +npm run test -w apps/frontend +npm run build -w apps/frontend +``` + +Expected: all three commands pass after the boundary cleanup changes land. + +- [ ] **Step 2: Verify no behavior drift** + +Confirm that the UI and API contracts still behave the same after import and export boundary changes. diff --git a/docs/features/frontend-shared-boundary-cleanup/spec.md b/docs/features/frontend-shared-boundary-cleanup/spec.md new file mode 100644 index 0000000..29e3ff2 --- /dev/null +++ b/docs/features/frontend-shared-boundary-cleanup/spec.md @@ -0,0 +1,53 @@ +# Frontend Shared Boundary Cleanup + +Дата: 2026-06-23 +Статус: выполнено + +## Контекст + +FSD-миграция уже убрала большую часть legacy-imports, но после крупного рефакторинга обычно остаются +тонкие границы, которые сложно заметить без отдельного аудита: слишком широкий `shared` public API, +дублирующие экспортные точки, и отдельные cross-layer или cross-entity dependencies, которые формально +работают, но ухудшают архитектурную ясность. + +Эта фича нужна, чтобы сузить shared/public surface и убрать архитектурные серые зоны без изменения +поведения экранов. + +## Цель + +Сделать frontend layer boundaries более явными: shared должен экспортировать только truly shared +поверхность, а доменные сущности и виджеты должны общаться через свои public entrypoints. + +## Требования + +### 1. Сузить shared public API + +`apps/frontend/src/shared/api` должен содержать только то, что действительно используется как shared +инфраструктура. Доменная поверхность должна быть разнесена по своим entity API/entrypoints. + +### 2. Устранить boundary ambiguity + +Любые архитектурно сомнительные cross-entity или cross-widget зависимости должны либо быть убраны, +либо явно перенесены на public barrel entrypoints. + +### 3. Сохранить runtime behavior + +Изменения должны быть ограничены реорганизацией импортов и export boundaries. Бизнес-логика и UI +поведение не меняются. + +### 4. Зафиксировать public API правила + +Фича должна завершиться с понятным описанием того, что считается public API каждого frontend слоя. + +## Ограничения + +- Не выполнять UI redesign. +- Не менять backend contracts. +- Не переписывать feature logic вне boundary cleanup. + +## Критерии приемки + +- Shared API surface стал уже и понятнее, чем до фичи. +- Cross-layer / cross-entity зависимости используют public barrels или удалены. +- Описание public API слоёв frontend обновлено в docs. +- Поведение UI и API-контракты не изменились. diff --git a/docs/features/frontend-shared-boundary-cleanup/tasks.md b/docs/features/frontend-shared-boundary-cleanup/tasks.md new file mode 100644 index 0000000..2abaa5d --- /dev/null +++ b/docs/features/frontend-shared-boundary-cleanup/tasks.md @@ -0,0 +1,28 @@ +# Frontend Shared Boundary Cleanup — tasks + +Статус: completed + +## 1. Найти boundary ambiguity + +- [x] Проверить `apps/frontend/src/shared/api/index.ts` на слишком широкие exports +- [x] Проверить `apps/frontend/src/entities/*/index.ts` на недостающие public entrypoints +- [x] Проверить `apps/frontend/src/widgets/*/index.ts` на конфликтующие или неявные зависимости + +## 2. Сузить shared/public surface + +- [x] Убрать из `shared/api` то, что является доменной convenience-обёрткой, а не shared infrastructure +- [x] Переключить доменные потребители на entity barrels +- [x] Убедиться, что новые imports не обходят public API слои + +## 3. Обновить документацию слоёв + +- [x] Обновить `apps/docs/docs/frontend/overview.md` +- [x] Обновить `apps/docs/docs/frontend/api-client.md` +- [x] Зафиксировать правила публичных API слоёв для shared/entities/widgets + +## 4. Финальная проверка + +- [x] Запустить `npm run lint -w apps/frontend` +- [x] Запустить `npm run test -w apps/frontend` +- [x] Запустить `npm run build -w apps/frontend` +- [x] Убедиться, что изменения не затронули runtime-поведение diff --git a/docs/features/frontend-test-hygiene/plan.md b/docs/features/frontend-test-hygiene/plan.md new file mode 100644 index 0000000..7e9e45d --- /dev/null +++ b/docs/features/frontend-test-hygiene/plan.md @@ -0,0 +1,93 @@ +# Frontend Test Hygiene Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Simplify and normalize the frontend test layer so helpers stay minimal, conventions stay consistent, and existing coverage remains stable. + +**Architecture:** This is a test-layer cleanup pass. First inspect the shared test helpers and conventions, then remove or narrow anything that is too broad or duplicated, then confirm that the remaining test setup still supports the existing suites. No new test platform is introduced and no product behavior should change. + +**Tech Stack:** Vitest, Testing Library, MSW, jsdom, existing frontend test helpers and conventions. + +--- + +### Task 1: Inspect the current test helpers + +**Files:** +- Read: `apps/frontend/src/test/setup.ts` +- Read: `apps/frontend/src/test/server.ts` +- Read: `apps/frontend/src/test/handlers.ts` +- Read: `apps/frontend/src/test/test-utils.tsx` +- Read: `apps/frontend/src/test/factories.ts` +- Read: `apps/frontend/vitest.config.ts` +- Read: `docs/features/frontend-test-coverage/spec.md` + +- [ ] **Step 1: Inventory shared helpers and wrappers** + +List what each shared test file does and whether it is still minimal or has grown into broad utility code. + +- [ ] **Step 2: Identify duplicated conventions** + +Check whether conventions around `QueryClient`, MSW, router setup, and auth/session wrapping are repeated in multiple places. + +### Task 2: Narrow the helpers + +**Files:** +- Modify: `apps/frontend/src/test/test-utils.tsx` +- Modify: `apps/frontend/src/test/factories.ts` +- Modify: `apps/frontend/src/test/handlers.ts` only if the defaults are too broad +- Modify: any test file that is currently compensating for an overly broad helper + +- [ ] **Step 1: Keep render helpers focused** + +Trim `renderWithProviders` or related wrappers down to the smallest shared surface needed by the existing test suite. + +- [ ] **Step 2: Reduce helper duplication** + +Move one-off setup back into the tests that need it instead of keeping it in a global helper. + +- [ ] **Step 3: Keep shared data factories minimal** + +Ensure factory data only covers the fields that are actually shared across multiple tests. + +### Task 3: Normalize conventions + +**Files:** +- Modify: `apps/frontend/vitest.config.ts` only if the config still carries unnecessary test defaults +- Modify: `apps/frontend/src/test/setup.ts` +- Modify: docs that describe frontend testing conventions +- Modify: `apps/docs/docs/frontend/overview.md` or the most relevant frontend test docs page + +- [ ] **Step 1: Keep the test setup explicit** + +Make sure global setup only contains the shared primitives that every test needs. + +- [ ] **Step 2: Align docs with the actual test strategy** + +Describe the current conventions in docs so new tests follow the same pattern instead of inventing local helpers. + +### Task 4: Verify coverage remains stable + +**Files:** +- Read: changed test helper files and docs +- Test: existing frontend test suite + +- [ ] **Step 1: Run the frontend test suite** + +Run: + +```bash +npm run test -w apps/frontend +``` + +Expected: existing tests continue to pass after the hygiene cleanup. + +- [ ] **Step 2: Run lint and build** + +Run: + +```bash +npm run lint -w apps/frontend +npm run build -w apps/frontend +``` + +Expected: both commands pass and no runtime behavior has changed. diff --git a/docs/features/frontend-test-hygiene/spec.md b/docs/features/frontend-test-hygiene/spec.md new file mode 100644 index 0000000..7b8e7a1 --- /dev/null +++ b/docs/features/frontend-test-hygiene/spec.md @@ -0,0 +1,53 @@ +# Frontend Test Hygiene + +Дата: 2026-06-23 +Статус: выполнено + +## Контекст + +Во frontend уже есть Vitest, Testing Library и MSW, но после нескольких фаз миграции тестовая +инфраструктура может накопить лишние абстракции, дублирующиеся helpers и разъехавшиеся conventions. +Это не проблема покрытия как такового, а проблема ясности, локальности и поддержки тестов. + +Эта фича нужна, чтобы тестовый слой оставался простым: тесты должны быть рядом с кодом, helpers должны +быть минимальными, а сетевые и контекстные зависимости должны быть предсказуемыми. + +## Цель + +Упростить и нормализовать frontend test infrastructure так, чтобы тесты было легче писать, читать и +поддерживать без изменения продуктового поведения. + +## Требования + +### 1. Test helpers stay minimal + +Общие test helpers должны содержать только действительно shared тестовую инфраструктуру. Дублирующие +или слишком широкие обёртки нужно убрать или сузить. + +### 2. Testing conventions stay consistent + +Frontend тесты должны следовать единым правилам по расположению, mock strategy, QueryClient setup и +MSW usage. Новые тестовые паттерны не должны вводить отдельные локальные договорённости без причины. + +### 3. Coverage is preserved + +Рефакторинг тестовой инфраструктуры не должен уменьшать существующее покрытие или ломать тесты в +колокации с кодом. + +### 4. No production behavior changes + +Фича касается только test layer. Production code changes допускаются только если они неизбежны для +упрощения тестовой поверхности, и тогда должны быть минимальными. + +## Ограничения + +- Не переписывать всю тестовую базу целиком. +- Не добавлять новую тестовую платформу. +- Не менять backend test strategy. + +## Критерии приемки + +- Test helpers и wrappers стали проще или уже, чем до фичи. +- Основные frontend тесты продолжают проходить. +- Тестовая документация описывает актуальные conventions. +- Не изменено пользовательское runtime-поведение. diff --git a/docs/features/frontend-test-hygiene/tasks.md b/docs/features/frontend-test-hygiene/tasks.md new file mode 100644 index 0000000..d838b54 --- /dev/null +++ b/docs/features/frontend-test-hygiene/tasks.md @@ -0,0 +1,28 @@ +# Frontend Test Hygiene — tasks + +Статус: completed + +## 1. Проверить тестовые helpers + +- [x] Проверить `apps/frontend/src/shared/lib/test/test-utils.tsx` на избыточные обёртки +- [x] Проверить `apps/frontend/src/shared/lib/test/factories.ts` на слишком широкие mock fixtures +- [x] Проверить `apps/frontend/src/shared/lib/test/handlers.ts` на лишние defaults + +## 2. Сузить test layer + +- [x] Убрать лишнюю глобальную магию из shared test setup +- [x] Перенести one-off setup в конкретные тесты, если он не нужен всем +- [x] Оставить только действительно shared helpers + +## 3. Нормализовать conventions + +- [x] Обновить frontend docs, описывающие test strategy и conventions +- [x] Убедиться, что global setup не распухает и остаётся понятным +- [x] Сверить conventions с `frontend-test-coverage` как отдельной фичей + +## 4. Финальная проверка + +- [x] Запустить `npm run test -w apps/frontend` +- [x] Запустить `npm run lint -w apps/frontend` +- [x] Запустить `npm run build -w apps/frontend` +- [x] Убедиться, что изменения не меняют пользовательское поведение diff --git a/docs/inbox.md b/docs/inbox.md index 0c77c03..86ea752 100644 --- a/docs/inbox.md +++ b/docs/inbox.md @@ -192,6 +192,16 @@ cash flow, бюджеты, аналитика, прогнозы и автома `SharePositionTable` → `BondPositionTable`, сначала уточнив минимальный API `DataTable` на основе реальных кейсов. +### Провести аудит frontend debt backlog + +- Сначала зафиксировать текущий frontend debt как отдельную audit-фичу, а не как одну большую + cleanup-инициативу. +- Разделить открытые пункты на небольшие follow-up фичи: docs sync, infrastructure hardening, shared + API/boundary cleanup. +- Не смешивать аудит с реализацией follow-up задач; audit должен только подтвердить актуальное + состояние и приоритеты. +- Эпик для этой декомпозиции: `Frontend Debt Backlog`. + ### Исследовать Backend-Driven UI - Рассматривать BDUI как исследовательскую гипотезу, а не выбранную целевую архитектуру. @@ -344,6 +354,11 @@ cash flow, бюджеты, аналитика, прогнозы и автома технический эпик с границами итерации, acceptance criteria, plan и tasks. Не объединять все пункты в один большой рефакторинг без декомпозиции. +> **Обновление 2026-06-24:** Проведён audit `frontend-debt-audit`. Созданы и выполнены 4 follow-up +> фичи: `frontend-docs-sync`, `frontend-infrastructure-hardening`, `frontend-shared-boundary-cleanup`, +> `frontend-test-hygiene`. Пункт P2 «Двойная система API-типов» — resolved (codegen unification). +> Остальные пункты ниже остаются открытыми и нуждаются в отдельных фичах. + Текущее состояние quality gates хорошее: на момент аудита проходят lint, format-check, backend build, frontend build, 94 backend-теста и 168 frontend-тестов. @@ -398,6 +413,7 @@ frontend build, 94 backend-теста и 168 frontend-тестов. ### P2: устранить двойную систему frontend API-типов +- [x] **RESOLVED** — codegen unification выполнена, `responses.ts` удалён, единый `types.ts` из OpenAPI. - `src/api/types.ts` генерируется из OpenAPI, но frontend в основном использует вручную поддерживаемый `src/api/responses.ts`. - Выбрать source of truth и миграционный путь к generated contract types, сохранив вручную только diff --git a/docs/roadmap.md b/docs/roadmap.md index 322720b..659beae 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -80,11 +80,29 @@ Roadmap отражает порядок продуктовой работы, н - [x] [Pilot-миграция](features/pilot-migration/spec.md) — HomePage + SearchBar на DS. - [x] [Security screener](features/security-screener/spec.md) — Phase 1: фильтры, таблица, backend. - [x] [MVP](features/moex-vibe/spec.md) — поиск, карточки акций/облигаций, графики, дивиденды. +- [x] [Frontend debt audit and backlog](features/frontend-debt-audit/spec.md) — audit frontend-техдолга, + разделение open items на 4 follow-up фичи, синхронизация inbox/roadmap +- [x] [frontend-docs-sync](features/frontend-docs-sync/spec.md) — синхронизация docs с состоянием кода +- [x] [frontend-infrastructure-hardening](features/frontend-infrastructure-hardening/spec.md) — + browser mock mode, env validation, tooling consistency, contract freshness +- [x] [frontend-shared-boundary-cleanup](features/frontend-shared-boundary-cleanup/spec.md) — + сужение shared/public API, устранение boundary ambiguity +- [x] [frontend-test-hygiene](features/frontend-test-hygiene/spec.md) — минимизация test helpers, + нормализация conventions ## Кандидаты следующих фич - [ ] [Миграция таблиц на дизайн-систему](features/table-migration/spec.md) — перевести legacy-таблицы на `DataTable` поверх `TanStack Table`. +- [ ] T-Bank data isolation and multi-tenancy (P0/P1) — изолировать данные T-Bank по пользователям, + ownership модель +- [ ] API envelope runtime contract (P1) — устранить double-wrapping, унифицировать envelope +- [ ] Auth security hardening (P1) — production-секреты, CORS allowlist, error masking, rate limiting +- [ ] Local T-Bank read-path (P1) — чтение истории операций из локальной БД вместо прямого вызова T-Bank +- [ ] Session model for multiple surfaces (P1/P2) — device-level сессии, rotation, reuse detection +- [ ] Type safety hardening (P2) — включение `no-explicit-any`, устранение `as any` в gRPC/screener/tests +- [ ] Testing strategy expansion (P2) — coverage thresholds, contract tests, Playwright smoke +- [ ] Frontend delivery optimization (P3) — route-level lazy loading, performance budgets - [ ] Аналитика портфеля Phases 2–3 — дивидендный доход, сравнение с target allocation. - [ ] Quality gate — завершить оставшиеся AC. - [ ] Broker-events — UX доработки и смешанный календарь.