Compare commits

...

10 Commits

27 changed files with 1292 additions and 103 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ vite.config.js
apps/docs/.docusaurus/ apps/docs/.docusaurus/
apps/docs/build/ apps/docs/build/
.idea .idea
.playwright-mcp

View File

@ -13,7 +13,7 @@ npm run codegen -w apps/frontend
Выполняет: Выполняет:
```bash ```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-контракта - 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'овым и поддерживаются вручную.

View File

@ -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 build -w apps/frontend` | `tsc -b && vite build` |
| `npm run preview -w apps/frontend` | `vite preview` | | `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 lint -w apps/frontend` | ESLint для `src/**/*.{ts,tsx}` |
| `npm run test -w apps/frontend` | Frontend Vitest suite | | `npm run test -w apps/frontend` | Frontend Vitest suite |

View File

@ -39,17 +39,68 @@ npm run test:watch -w apps/backend
## Тесты frontend ## Тесты frontend
Фреймворк: **Vitest 4** + **React Testing Library** + **MSW**. Фреймворк: **Vitest** + **React Testing Library** + **MSW**.
Запуск: ### Запуск
```bash ```bash
npm run test:frontend npm run test:frontend # все тесты
# или npm run test -w apps/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(<StockDetails stock={stock} />)
expect(screen.getByText('Сбер (SBER)')).toBeInTheDocument()
```
**Компонент с auth/Router** — `renderWithProviders`:
```tsx
import { renderWithProviders } from '@/shared/lib/test/test-utils'
renderWithProviders(<ProfilePage />, { 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 ## Тесты design system

View File

@ -1,8 +1,8 @@
# API client # API client
## Клиент (`api/client.ts`) ## Клиент (`shared/api/kyClient.ts`)
Использует нативный `fetch` с единой обёрткой `request<T>`. Использует `ky` с единой обёрткой `request<T>`.
```typescript ```typescript
async function request<T>( async function request<T>(
@ -13,9 +13,14 @@ async function request<T>(
``` ```
- Формирует URL из `path` + query params - Формирует URL из `path` + query params
- Парсит JSON-ответ в `ApiEnvelope<{ data: T, meta: ApiResponseMeta }>` - Парсит JSON-ответ и нормализует envelope через `normalizeEnvelope()`
- Выбрасывает `Error` при HTTP-ошибке - Выбрасывает `Error` при HTTP-ошибке
## Public API (`shared/api/index.ts`)
Публичная точка входа для frontend API — `shared/api/index.ts`. Оттуда экспортируются `request`,
`configureKyAuth`, `getHealth` и DTO alias-ы.
## API functions ## API functions
| Function | Method | Path | | Function | Method | Path |
@ -50,7 +55,7 @@ async function request<T>(
## Типы ## Типы
Ручные типы ответов в `api/responses.ts`: Публичные DTO alias-ы в `shared/api/index.ts`:
- `ApiResponseMeta``{ cachedAt, fromCache }` - `ApiResponseMeta``{ cachedAt, fromCache }`
- `ApiEnvelope<T>``{ data: T, meta: ApiResponseMeta }` - `ApiEnvelope<T>``{ data: T, meta: ApiResponseMeta }`
@ -62,4 +67,4 @@ async function request<T>(
- `Portfolio`, `PortfolioDetail`, `Position`, `PortfolioSummary`, `AnalyticsResponse` - `Portfolio`, `PortfolioDetail`, `Position`, `PortfolioSummary`, `AnalyticsResponse`
- `ScreenerItem`, `ScreenerResult` - `ScreenerItem`, `ScreenerResult`
Codegen-типы из OpenAPI в `api/types.ts` (генерируются через `npm run codegen`). Codegen-типы из OpenAPI в `shared/api/types.ts` (генерируются через `npm run codegen -w apps/frontend`).

View File

@ -24,6 +24,11 @@
- broker-event hooks: `entities/broker-event/index.ts` - broker-event hooks: `entities/broker-event/index.ts`
- session hooks: `entities/session/index.ts` - session hooks: `entities/session/index.ts`
## Test helpers
- `renderWithProviders``shared/lib/test/test-utils.tsx`
- `TestSessionProvider``shared/lib/test/TestSessionProvider.tsx`
## Конфигурация Query ## Конфигурация Query
```typescript ```typescript
@ -40,9 +45,9 @@ const queryClient = new QueryClient({
## Паттерн hook ## Паттерн hook
1. Хук вызывает domain API helper из `entities/*/api/` или `shared/api/client` 1. Хук вызывает domain API helper из `entities/*/api/` или `shared/api`
2. Извлекает `res.data` (ответ API обёрнут в `{ data, meta }`) 2. Извлекает `res.data` (ответ API обёрнут в `{ data, meta }`)
3. Типизируется через response types из `shared/api/responses.ts` 3. Типизируется через response types из `shared/api`
```typescript ```typescript
export function useStock(secid: string) { export function useStock(secid: string) {

View File

@ -5,10 +5,10 @@ React SPA, собранная с Vite.
## Технологический стек ## Технологический стек
- React 18 - React 18
- react-router-dom v6 - @tanstack/react-router
- TanStack Query v5 - TanStack Query v5
- lightweight-charts v4 - lightweight-charts v4
- openapi-fetch (с рукописными типами `responses.ts`) - ky + OpenAPI-generated types
- Vitest + Testing Library + MSW - Vitest + Testing Library + MSW
- Vite 5 - Vite 5
@ -21,14 +21,15 @@ Published-структура ниже описывает primary FSD entrypoints
apps/frontend/src/ apps/frontend/src/
├── main.tsx # Точка входа ├── main.tsx # Точка входа
├── app/ # FSD app layer ├── app/ # FSD app layer
│ ├── App.tsx # BrowserRouter → AppRoutes │ ├── App.tsx # RouterProvider → router
│ ├── index.ts # barrel │ ├── index.ts # barrel
│ ├── providers/ │ ├── providers/
│ │ ├── AppProviders.tsx # QueryClientProvider + SessionProvider │ │ ├── AppProviders.tsx # QueryClientProvider + SessionProvider
│ │ ├── SessionProvider.tsx │ │ ├── SessionProvider.tsx
│ │ └── index.ts │ │ └── index.ts
│ ├── routing/ │ ├── routing/
│ │ ├── AppRoutes.tsx # Все маршруты │ │ ├── routeTree.tsx # TanStack Router tree
│ │ ├── router.ts # router export
│ │ ├── ProtectedRoute.tsx │ │ ├── ProtectedRoute.tsx
│ │ └── index.ts │ │ └── index.ts
│ └── layouts/ │ └── layouts/
@ -37,7 +38,10 @@ apps/frontend/src/
├── features/ # FSD features ├── features/ # FSD features
│ └── screener/ # Скринер ценных бумаг (api, model, ui) │ └── screener/ # Скринер ценных бумаг (api, model, ui)
├── shared/ ├── 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 │ └── ui/ # shared UI primitives without domain logic
├── entities/ # FSD business entities ├── entities/ # FSD business entities
│ ├── session/ # Auth/session (api, model) │ ├── session/ # Auth/session (api, model)
@ -79,13 +83,6 @@ apps/frontend/src/
│ ├── broker-events/ # FSD: page entrypoint │ ├── broker-events/ # FSD: page entrypoint
│ ├── broker-positions/ # FSD: page entrypoint │ ├── broker-positions/ # FSD: page entrypoint
│ └── broker-operations/ # 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 └── styles.css
``` ```
@ -96,9 +93,15 @@ apps/frontend/src/
Создан `app/` слой FSD, в который перенесены инфраструктурные модули: Создан `app/` слой FSD, в который перенесены инфраструктурные модули:
- `app/providers/` — композиция провайдеров (SessionProvider, QueryClientProvider) - `app/providers/` — композиция провайдеров (SessionProvider, QueryClientProvider)
- `app/routing/`маршруты и ProtectedRoute - `app/routing/`route tree и guard'ы
- `app/layouts/` — AppLayout (шапка + Outlet) - `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 ### entities
@ -106,7 +109,7 @@ apps/frontend/src/
| Сущность | api | model | ui | | Сущность | 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 | — | | `stock` | getStock, getStockCandles, getStockDividends | useStock, useStockCandles, useStockDividends | — |
| `bond` | getBond, getBondCandles | useBond, useBondCandles | — | | `bond` | getBond, getBondCandles | useBond, useBondCandles | — |
| `portfolio` | CRUD портфелей и позиций, аналитика | usePortfolio, usePortfolios, usePortfolioAnalytics, usePortfolioMutations, usePositionMutations | — | | `portfolio` | CRUD портфелей и позиций, аналитика | usePortfolio, usePortfolios, usePortfolioAnalytics, usePortfolioMutations, usePositionMutations | — |
@ -130,6 +133,13 @@ apps/frontend/src/
- `portfolio-card`, `portfolio-form`, `portfolio-summary`, `portfolio-analytics` — UI портфелей - `portfolio-card`, `portfolio-form`, `portfolio-summary`, `portfolio-analytics` — UI портфелей
- `share-positions-table`, `bond-positions-table` — таблицы позиций - `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
- `pages/home`, `pages/stock`, `pages/bond` — FSD page entrypoints для market pages - `pages/home`, `pages/stock`, `pages/bond` — FSD page entrypoints для market pages

View File

@ -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 | Доступ | Описание | | Path | Component | Доступ | Описание |
|---|---|---|---| |---|---|---|---|
| `/` | `HomePage` from `pages/home` | Public | Главная страница | | `/` | `HomePage` from `pages/home` | Public | Главная страница |
| `/stocks/:secid` | `StockPage` from `pages/stock` | Public | Страница акции | | `/stocks/$secid` | `StockPage` from `pages/stock` | Public | Страница акции |
| `/bonds/:secid` | `BondPage` from `pages/bond` | Public | Страница облигации | | `/bonds/$secid` | `BondPage` from `pages/bond` | Public | Страница облигации |
| `/screener` | `ScreenerPage` | Public | Скринер ценных бумаг | | `/screener` | `ScreenerPage` | Public | Скринер ценных бумаг |
| `/login` | `LoginPage` | Public | Вход | | `/login` | `LoginPage` | Public | Вход |
| `/register` | `RegisterPage` | Public | Регистрация | | `/register` | `RegisterPage` | Public | Регистрация |
| `/profile` | `ProfilePage` | Protected | Профиль текущего пользователя | | `/profile` | `ProfilePage` | Protected | Профиль текущего пользователя |
| `/portfolios` | `PortfoliosListPage` | Protected | Список портфелей | | `/portfolios` | `PortfoliosListPage` | Protected | Список портфелей |
| `/portfolios/:id` | `PortfolioDetailPage` | Protected | Детальная страница портфеля | | `/portfolios/$id` | `PortfolioDetailPage` | Protected | Детальная страница портфеля |
| `/broker` | `BrokerAccountsPage` from `pages/broker-accounts` | Protected | Список брокерских счетов | | `/broker` | `BrokerAccountsPage` from `pages/broker-accounts` | Protected | Список брокерских счетов |
| `/broker/:accountId` | `BrokerAccountLayout` + nested pages | Protected | Детальная область брокерского счёта | | `/broker/$accountId` | `BrokerAccountLayout` + nested pages | Protected | Детальная область брокерского счёта |
| `/broker/:accountId/events` | `BrokerEventsPage` from `pages/broker-events` | Protected | Календарь событий и выплат | | `/broker/$accountId/events` | `BrokerEventsPage` from `pages/broker-events` | Protected | Календарь событий и выплат |
Все page entrypoints живут в FSD-слоях: Все page entrypoints живут в FSD-слоях:
@ -37,67 +37,12 @@ Source of truth для маршрутов: `apps/frontend/src/app/routing/AppRou
## Структура маршрутов ## Структура маршрутов
```tsx ```tsx
<Routes> Маршруты собираются через TanStack Router в `routeTree.tsx`.
<Route element={<AppLayout />}>
<Route path="/" element={<HomePage />} />
<Route path="/stocks/:secid" element={<StockPage />} />
<Route path="/bonds/:secid" element={<BondPage />} />
<Route path="/screener" element={<ScreenerPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route
path="/profile"
element={
<ProtectedRoute>
<ProfilePage />
</ProtectedRoute>
}
/>
<Route
path="/portfolios"
element={
<ProtectedRoute>
<PortfoliosListPage />
</ProtectedRoute>
}
/>
<Route
path="/portfolios/:id"
element={
<ProtectedRoute>
<PortfolioDetailPage />
</ProtectedRoute>
}
/>
<Route
path="/broker"
element={
<ProtectedRoute>
<BrokerAccountsPage />
</ProtectedRoute>
}
/>
<Route
path="/broker/:accountId"
element={
<ProtectedRoute>
<BrokerAccountLayout />
</ProtectedRoute>
}
>
<Route index element={<BrokerAccountOverviewPage />} />
<Route path="shares" element={<BrokerPositionsPage type="share" title="Акции" />} />
<Route path="bonds" element={<BrokerPositionsPage type="bond" title="Облигации" />} />
<Route path="operations" element={<BrokerOperationsPage />} />
<Route path="events" element={<BrokerEventsPage />} />
</Route>
</Route>
</Routes>
``` ```
## Композиция страницы событий ## Композиция страницы событий
Страница `/broker/:accountId/events` собирается из FSD-слоёв: Страница `/broker/$accountId/events` собирается из FSD-слоёв:
```mermaid ```mermaid
flowchart TB flowchart TB

View File

@ -1,9 +1,75 @@
# Tests # Frontend Testing Conventions
## Common issues ## Helpers
### Auth loading screen ### renderWithProviders (`test-utils.tsx`)
Components rendered through `renderWithProviders` are wrapped in AuthProvider which shows
a loading screen until `POST /api/v1/auth/refresh` resolves. Wraps component in `QueryClientProvider` + `TestSessionProvider` + `RouterProvider`.
- Use `await screen.findByText()` to wait for auth to complete.
- For components that don't need auth, render with just QueryClientProvider + MemoryRouter. Use for components that depend on auth or routing.
```ts
import { renderWithProviders } from '@/shared/lib/test/test-utils'
renderWithProviders(<ProfilePage />, { 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(<StockDetails stock={createMockShare()} />)
```
### 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`.

View File

@ -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

View File

@ -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.

View File

@ -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-пунктов (P0P3) от 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

View File

@ -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-пунктов (P0P3), из них:
- 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] Проверить, что спецификация, план и задачи не противоречат друг другу

View File

@ -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.

View File

@ -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-файлы приложения.

View File

@ -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` не осталось устаревших миграционных заметок без статуса

View File

@ -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.

View File

@ -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 пользовательского приложения.

View File

@ -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

View File

@ -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.

View File

@ -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-контракты не изменились.

View File

@ -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-поведение

View File

@ -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.

View File

@ -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-поведение.

View File

@ -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] Убедиться, что изменения не меняют пользовательское поведение

View File

@ -192,6 +192,16 @@ cash flow, бюджеты, аналитика, прогнозы и автома
`SharePositionTable``BondPositionTable`, сначала уточнив минимальный API `DataTable` на основе `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 ### Исследовать Backend-Driven UI
- Рассматривать BDUI как исследовательскую гипотезу, а не выбранную целевую архитектуру. - Рассматривать BDUI как исследовательскую гипотезу, а не выбранную целевую архитектуру.
@ -344,6 +354,11 @@ cash flow, бюджеты, аналитика, прогнозы и автома
технический эпик с границами итерации, acceptance criteria, plan и tasks. Не объединять все пункты в технический эпик с границами итерации, 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, Текущее состояние quality gates хорошее: на момент аудита проходят lint, format-check, backend build,
frontend build, 94 backend-теста и 168 frontend-тестов. frontend build, 94 backend-теста и 168 frontend-тестов.
@ -398,6 +413,7 @@ frontend build, 94 backend-теста и 168 frontend-тестов.
### P2: устранить двойную систему frontend API-типов ### P2: устранить двойную систему frontend API-типов
- [x] **RESOLVED** — codegen unification выполнена, `responses.ts` удалён, единый `types.ts` из OpenAPI.
- `src/api/types.ts` генерируется из OpenAPI, но frontend в основном использует вручную поддерживаемый - `src/api/types.ts` генерируется из OpenAPI, но frontend в основном использует вручную поддерживаемый
`src/api/responses.ts`. `src/api/responses.ts`.
- Выбрать source of truth и миграционный путь к generated contract types, сохранив вручную только - Выбрать source of truth и миграционный путь к generated contract types, сохранив вручную только

View File

@ -80,11 +80,29 @@ Roadmap отражает порядок продуктовой работы, н
- [x] [Pilot-миграция](features/pilot-migration/spec.md) — HomePage + SearchBar на DS. - [x] [Pilot-миграция](features/pilot-migration/spec.md) — HomePage + SearchBar на DS.
- [x] [Security screener](features/security-screener/spec.md) — Phase 1: фильтры, таблица, backend. - [x] [Security screener](features/security-screener/spec.md) — Phase 1: фильтры, таблица, backend.
- [x] [MVP](features/moex-vibe/spec.md) — поиск, карточки акций/облигаций, графики, дивиденды. - [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-таблицы - [ ] [Миграция таблиц на дизайн-систему](features/table-migration/spec.md) — перевести legacy-таблицы
на `DataTable` поверх `TanStack Table`. на `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 23 — дивидендный доход, сравнение с target allocation. - [ ] Аналитика портфеля Phases 23 — дивидендный доход, сравнение с target allocation.
- [ ] Quality gate — завершить оставшиеся AC. - [ ] Quality gate — завершить оставшиеся AC.
- [ ] Broker-events — UX доработки и смешанный календарь. - [ ] Broker-events — UX доработки и смешанный календарь.