docs: translate quality gate spec to russian

This commit is contained in:
Sergey Krylov 2026-06-14 21:50:58 +03:00
parent ee88b29181
commit 2e79e69403

View File

@ -1,92 +1,94 @@
# Quality Gate, API Contract, and Documentation Refresh Design
# Дизайн стабилизации quality gate, API-контракта и документации
## Status
## Статус
Approved for specification on 2026-06-14.
Одобрено для спецификации 2026-06-14.
## PRD
### Problem
### Проблема
MoexVibe has accumulated coordination debt between tests, generated contracts, and documentation.
The application still builds, but the default backend quality gate is not trustworthy:
В MoexVibe накопился координационный технический долг между тестами, сгенерированными контрактами
и документацией. Приложение всё ещё собирается, но стандартный backend quality gate сейчас нельзя
считать надёжным:
- `npm run lint` fails on an unused variable in a backend test.
- `npm run test:backend` fails because some backend tests call the live MOEX API through the real
`MoexClientService`.
- The live MOEX failures surface as Vitest `DataCloneError` reports because Axios errors contain
non-cloneable request configuration functions.
- `docs/openapi/openapi.yaml` and `apps/frontend/src/api/types.ts` do not include current `auth`,
`portfolios`, and `securities/screener` endpoints.
- README, AGENTS, and Docusaurus pages describe an older state of the repo in several places.
- `npm run build:docs` succeeds but emits Docusaurus broken-link warnings for `/`.
- `npm run lint` падает из-за неиспользуемой переменной в backend-тесте.
- `npm run test:backend` падает, потому что часть backend-тестов обращается к живому MOEX API через
настоящий `MoexClientService`.
- Ошибки live MOEX-запросов проявляются как Vitest `DataCloneError`, потому что `AxiosError`
содержит функции в конфигурации запроса, которые нельзя клонировать между worker'ами.
- `docs/openapi/openapi.yaml` и `apps/frontend/src/api/types.ts` не содержат актуальные эндпоинты
`auth`, `portfolios` и `securities/screener`.
- README, AGENTS и страницы Docusaurus местами описывают старое состояние репозитория.
- `npm run build:docs` успешно генерирует статические файлы, но выводит предупреждения Docusaurus о
broken link на `/`.
This makes future feature work slower: contributors cannot tell which command output matters, which
API contract is current, or whether backend tests are failing because of application behavior or a
network dependency.
Из-за этого следующие задачи делать медленнее: разработчику неочевидно, какой вывод команд важен,
какой API-контракт актуален и почему backend-тесты падают: из-за поведения приложения или из-за
сетевой зависимости.
### Goals
### Цели
1. Make default quality checks deterministic and suitable for local development and CI.
2. Keep live MOEX checks available, but move them out of the default unit-test path.
3. Re-establish a clear source of truth for the OpenAPI contract.
4. Regenerate or synchronize frontend OpenAPI types with the current backend routes.
5. Bring README, AGENTS, and Docusaurus docs in line with the current repo.
6. Remove actionable Docusaurus broken-link warnings from the docs build.
1. Сделать стандартные проверки детерминированными и пригодными для локальной разработки и CI.
2. Сохранить live MOEX-проверки, но вынести их из стандартного unit-test пути.
3. Вернуть понятный источник правды для OpenAPI-контракта.
4. Перегенерировать или синхронизировать frontend OpenAPI-типы с текущими backend routes.
5. Привести README, AGENTS и Docusaurus-документацию к текущему состоянию репозитория.
6. Убрать actionable предупреждения Docusaurus о broken links из `npm run build:docs`.
### Non-Goals
### Не входит в задачу
- No user-facing feature changes.
- No deep refactor of `PortfolioService` or `MoexClientService`.
- No migration to a fully generated frontend API client.
- No Redis, database, auth model, or portfolio analytics redesign.
- No CI provider migration.
- Пользовательские feature-изменения.
- Глубокий рефакторинг `PortfolioService` или `MoexClientService`.
- Переход frontend API-клиента на полностью сгенерированный клиент.
- Redis, изменение схемы БД, redesign auth-модели или portfolio analytics.
- Миграция CI-провайдера.
## Current Findings
## Текущие находки
### Passing Checks
### Проходящие проверки
- `npm run test:frontend` passes: 22 files, 95 tests.
- `npm run format:check` passes.
- `npm run build:backend` passes.
- `npm run build:frontend` passes.
- `npm run build:docs` produces static files successfully.
- `npm run test:frontend` проходит: 22 файла, 95 тестов.
- `npm run format:check` проходит.
- `npm run build:backend` проходит.
- `npm run build:frontend` проходит.
- `npm run build:docs` успешно генерирует статические файлы.
### Failing or Noisy Checks
### Падающие или шумные проверки
- `npm run lint` fails in
`apps/backend/src/modules/securities/screener.service.spec.ts` because `moexClient` is assigned
but not used.
- `npm run test:backend` fails with unhandled Vitest errors. The affected specs instantiate the real
`MoexClientService` and call MOEX:
- `npm run lint` падает в `apps/backend/src/modules/securities/screener.service.spec.ts`, потому
что `moexClient` присваивается, но не используется.
- `npm run test:backend` падает с unhandled Vitest errors. Затронутые specs создают настоящий
`MoexClientService` и ходят в MOEX:
- `apps/backend/src/modules/moex-client/moex-client.service.spec.ts`
- `apps/backend/src/modules/securities/securities.service.spec.ts`
- `apps/backend/src/modules/candles/candles.service.spec.ts`
- similar service specs for shares and bonds also rely on live MOEX access.
- `npm run build:docs` warns that many pages link to `/`.
- похожие service specs для shares и bonds тоже зависят от live MOEX-доступа.
- `npm run build:docs` предупреждает, что многие страницы ссылаются на `/`.
### Stale Documentation and Contract Artifacts
### Устаревшая документация и контрактные артефакты
- `AGENTS.md` says `npm run lint` is backend-only and frontend tests are absent.
- `apps/docs/docs/development/testing.md` says frontend tests are absent.
- `apps/docs/docs/development/commands.md` omits `test:frontend`, docs scripts, and frontend lint.
- `apps/docs/docs/frontend/routes.md` omits `/login`, `/register`, `/profile`, `/portfolios`,
`/portfolios/:id`, and `/screener`.
- `apps/docs/docs/frontend/overview.md` omits auth, portfolio, screener, and test directories.
- `apps/docs/docs/backend/api.md` omits portfolio and screener endpoints.
- `apps/docs/docs/backend/portfolio.md` documents `PATCH /api/v1/portfolios/:id/patch`, while the
controller implements `PATCH /api/v1/portfolios/:id`.
- `docs/openapi/openapi.yaml` and `apps/frontend/src/api/types.ts` only contain the early health,
search, shares, bonds, and candles paths.
- `AGENTS.md` говорит, что `npm run lint` проверяет только backend, а frontend-тестов нет.
- `apps/docs/docs/development/testing.md` говорит, что frontend-тестов нет.
- `apps/docs/docs/development/commands.md` не описывает `test:frontend`, docs scripts и frontend
lint.
- `apps/docs/docs/frontend/routes.md` не описывает `/login`, `/register`, `/profile`,
`/portfolios`, `/portfolios/:id` и `/screener`.
- `apps/docs/docs/frontend/overview.md` не описывает auth, portfolio, screener и test-директории.
- `apps/docs/docs/backend/api.md` не содержит portfolio и screener endpoints.
- `apps/docs/docs/backend/portfolio.md` документирует `PATCH /api/v1/portfolios/:id/patch`, хотя
controller реализует `PATCH /api/v1/portfolios/:id`.
- `docs/openapi/openapi.yaml` и `apps/frontend/src/api/types.ts` содержат только ранние paths для
health, search, shares, bonds и candles.
## Domain Model
## Доменная модель
### Quality Gate
A quality gate is a repeatable command that developers can run without external dependencies unless
the command explicitly says otherwise.
Quality gate: это повторяемая команда, которую разработчик может запускать без внешних зависимостей,
если сама команда явно не говорит обратного.
Default gates:
Стандартные проверки:
- `npm run lint`
- `npm run test:backend`
@ -96,106 +98,108 @@ Default gates:
- `npm run build:docs`
- `npm run format:check`
Opt-in gates:
Opt-in проверки:
- Live MOEX integration checks. These may use network access and should not run in default unit-test
or CI jobs unless explicitly requested.
- Live MOEX integration checks. Они могут требовать network access и не должны запускаться в
стандартных unit tests или CI jobs без явного запроса.
### Contract Source
### Источник API-контракта
The authoritative backend contract is the NestJS Swagger document generated from controllers and DTO
decorators at `/api/docs-json`.
Авторитетный backend contract: NestJS Swagger document, который генерируется из controllers и DTO
decorators по `/api/docs-json`.
Generated or synchronized artifacts:
Сгенерированные или синхронизированные артефакты:
- `docs/openapi/openapi.yaml` as a checked-in human-readable snapshot.
- `apps/frontend/src/api/types.ts` as generated TypeScript path and schema types.
- Docusaurus API pages as explanatory documentation, not the canonical machine contract.
- `docs/openapi/openapi.yaml`: checked-in человекочитаемый snapshot.
- `apps/frontend/src/api/types.ts`: сгенерированные TypeScript path и schema types.
- Docusaurus API pages: поясняющая документация, но не канонический machine contract.
### Documentation Source
### Источник документации
Documentation should describe the current repository state, not a historical implementation plan.
Superpowers specs and plans remain project history; README, AGENTS, and Docusaurus pages are the
current onboarding surface.
Документация должна описывать текущее состояние репозитория, а не исторический план реализации.
Superpowers specs и plans остаются историей проекта. README, AGENTS и Docusaurus pages являются
актуальной onboarding-поверхностью.
## ADR
### Decision
### Решение
Split backend tests into deterministic unit tests and opt-in live MOEX integration tests.
Разделить backend tests на детерминированные unit tests и opt-in live MOEX integration tests.
### Rationale
### Обоснование
The default backend test command currently mixes unit behavior with external network availability.
That makes failures ambiguous and produces noisy Vitest serialization errors when Axios rejects with
non-cloneable configuration fields. Unit tests should verify application logic with controlled
fixtures. Live MOEX tests are still valuable, but they belong in a separately named command with an
explicit environment requirement.
Стандартная backend test command сейчас смешивает unit-поведение и доступность внешней сети. Это
делает failures неоднозначными и порождает шумные Vitest serialization errors, когда Axios
возвращает rejection с non-cloneable configuration fields. Unit tests должны проверять логику
приложения на контролируемых fixtures. Live MOEX tests полезны, но должны быть отдельной явно
названной командой с понятным требованием к окружению.
### Consequences
### Последствия
- `npm run test:backend` becomes stable offline.
- Live MOEX coverage remains available through a dedicated integration command.
- Some existing specs will change from "real MOEX smoke test" to "service behavior with mocked
- `npm run test:backend` становится стабильной offline-командой.
- Live MOEX coverage остаётся доступным через отдельную integration command.
- Часть существующих specs изменится с "real MOEX smoke test" на "service behavior with mocked
`MoexClientService`".
- Contract drift becomes visible because OpenAPI snapshots and frontend generated types are updated
as part of this work.
- Contract drift станет видимым, потому что OpenAPI snapshots и frontend generated types будут
обновлены в рамках этой работы.
## Backend Architecture
### Unit Test Boundary
### Граница unit tests
Service tests for `SharesService`, `BondsService`, `CandlesService`, and `SecuritiesService` should
mock `MoexClientService` and `CacheService`.
Service tests для `SharesService`, `BondsService`, `CandlesService` и `SecuritiesService` должны
mock'ать `MoexClientService` и `CacheService`.
The mocked data should exercise behavior that matters to MoexVibe:
Mocked data должны проверять поведение, важное для MoexVibe:
- normalized share data is returned from cached or fetched MOEX client data;
- normalized bond data handles missing market fields as nullable values;
- candles are mapped into the public response shape;
- search and screener behavior uses deterministic fixture rows;
- cache metadata remains represented through `{ data, meta }` where service contracts require it.
- нормализованные share data возвращаются из cached или fetched MOEX client data;
- нормализованные bond data корректно обрабатывают отсутствующие market fields как nullable values;
- candles мапятся в public response shape;
- search и screener используют детерминированные fixture rows;
- cache metadata остаётся представленной через `{ data, meta }`, где этого требуют service
contracts.
### Live Integration Test Boundary
### Граница live integration tests
Live MOEX checks should be isolated in `*.integration.spec.ts` files or an equivalent explicit test
path. They should only run through a dedicated command such as `npm run test:integration -w
apps/backend` and should document that network access is required.
Live MOEX checks должны быть изолированы в `*.integration.spec.ts` files или эквивалентном явном
test path. Они должны запускаться только через отдельную команду, например
`npm run test:integration -w apps/backend`, и должны документировать, что для них требуется network
access.
The integration command should not be part of the default `npm run test:backend` command.
Integration command не должна входить в стандартный `npm run test:backend`.
### OpenAPI Decorators
### OpenAPI decorators
Controllers that already exist should expose enough Swagger metadata for generated path types:
Существующие controllers должны отдавать достаточно Swagger metadata для generated path types:
- Auth routes: register, login, refresh, logout, me, profile update.
- Securities routes: search and screener.
- Securities routes: search и screener.
- Portfolio routes: list, create, detail, update, delete, position mutations, analytics.
- Existing shares, bonds, candles, and health routes.
- Существующие shares, bonds, candles и health routes.
The implementation should prefer existing DTOs and response DTOs. If a response lacks a DTO and
adding one would be large, the first pass may use minimal response decorators while keeping runtime
behavior unchanged.
В реализации нужно предпочитать существующие DTO и response DTO. Если для response нет DTO и
добавление полного DTO слишком раздувает первый проход, можно использовать минимальные response
decorators без изменения runtime behavior.
## Frontend Architecture
### Generated Types
`apps/frontend/src/api/types.ts` should be regenerated from the current backend Swagger JSON after
backend Swagger metadata includes the current routes.
`apps/frontend/src/api/types.ts` должен быть перегенерирован из текущего backend Swagger JSON после
того, как backend Swagger metadata будет покрывать актуальные routes.
The existing hand-written `responses.ts` and API wrapper modules remain in place for this epic. The
goal is contract freshness, not a full client rewrite.
Существующие hand-written `responses.ts` и API wrapper modules остаются на месте в этом эпике. Цель:
свежесть контракта, а не полный rewrite клиента.
### Tests
Frontend tests already exist and pass. This epic should not rewrite frontend testing architecture.
If API response types change, update frontend tests only where the regenerated contract reveals a
real mismatch.
Frontend tests уже существуют и проходят. Этот эпик не должен переписывать frontend testing
architecture. Если API response types изменятся, frontend tests нужно обновлять только там, где
перегенерированный contract выявит реальное несоответствие.
## OpenAPI Contract Scope
The synchronized contract should include at least these paths under `/api/v1`:
Синхронизированный contract должен включать минимум эти paths под `/api/v1`:
- `GET /health`
- `POST /auth/register`
@ -229,21 +233,22 @@ The synchronized contract should include at least these paths under `/api/v1`:
### README
Update README so quickstart and test sections mention backend, frontend, and docs workspaces.
Обновить README так, чтобы quickstart и test sections упоминали backend, frontend и docs
workspaces.
### AGENTS
Update AGENTS to reflect:
Обновить AGENTS:
- `apps/docs` is part of the workspace.
- `npm run lint` runs backend and frontend lint.
- frontend tests exist.
- pre-commit checks exist through Husky and lint-staged.
- CI exists under `.gitea/workflows/ci.yml`.
- `apps/docs` является частью workspace.
- `npm run lint` запускает backend и frontend lint.
- frontend tests существуют.
- pre-commit checks существуют через Husky и lint-staged.
- CI существует в `.gitea/workflows/ci.yml`.
### Docusaurus
Update current onboarding pages:
Обновить текущие onboarding pages:
- development commands;
- testing;
@ -254,36 +259,36 @@ Update current onboarding pages:
- backend API;
- backend portfolio.
Fix Docusaurus config or docs links so `npm run build:docs` no longer reports broken links to `/`.
The separate update-check warning about `/Users/ksv741/.config` permissions is external to the repo
and does not need to be fixed in this epic.
Исправить Docusaurus config или docs links так, чтобы `npm run build:docs` больше не сообщал о
broken links на `/`. Отдельное update-check warning про permissions в `/Users/ksv741/.config`
является внешним к репозиторию и в этот эпик не входит.
## Implementation Phases
## Этапы реализации
### Phase 1: Stabilize Default Checks
### Этап 1: стабилизировать стандартные проверки
1. Fix the unused backend test variable that breaks lint.
2. Convert default backend service specs away from live MOEX calls.
3. Move or add live MOEX smoke coverage under an opt-in integration command.
4. Verify `npm run lint` and `npm run test:backend`.
1. Исправить неиспользуемую backend test variable, которая ломает lint.
2. Перевести стандартные backend service specs с live MOEX calls на mocked dependencies.
3. Вынести или добавить live MOEX smoke coverage под opt-in integration command.
4. Проверить `npm run lint` и `npm run test:backend`.
### Phase 2: Refresh Contract Artifacts
### Этап 2: обновить contract artifacts
1. Add or complete Swagger metadata for current routes.
2. Regenerate `apps/frontend/src/api/types.ts`.
3. Synchronize `docs/openapi/openapi.yaml` with the current contract.
4. Verify generated paths include auth, screener, and portfolio routes.
1. Добавить или завершить Swagger metadata для актуальных routes.
2. Перегенерировать `apps/frontend/src/api/types.ts`.
3. Синхронизировать `docs/openapi/openapi.yaml` с текущим contract.
4. Проверить, что generated paths включают auth, screener и portfolio routes.
### Phase 3: Refresh Documentation
### Этап 3: обновить документацию
1. Update README and AGENTS.
2. Update Docusaurus development, frontend, backend, and portfolio pages.
3. Fix Docusaurus broken `/` link warning.
4. Verify `npm run build:docs`.
1. Обновить README и AGENTS.
2. Обновить Docusaurus development, frontend, backend и portfolio pages.
3. Исправить Docusaurus broken `/` link warning.
4. Проверить `npm run build:docs`.
### Phase 4: Full Verification
### Этап 4: полная проверка
Run:
Запустить:
```bash
npm run lint
@ -297,30 +302,32 @@ npm run format:check
## Acceptance Criteria
- `npm run lint` exits 0.
- `npm run test:backend` exits 0 without live MOEX/network dependency.
- `npm run test:frontend` exits 0.
- `npm run build:backend` exits 0.
- `npm run build:frontend` exits 0.
- `npm run build:docs` exits 0 and no longer reports Docusaurus broken links for `/`.
- `npm run format:check` exits 0.
- `apps/frontend/src/api/types.ts` includes current auth, screener, and portfolio paths.
- `docs/openapi/openapi.yaml` includes current auth, screener, and portfolio paths.
- README, AGENTS, and Docusaurus docs no longer claim that frontend tests are absent.
- Portfolio docs use `PATCH /api/v1/portfolios/:id`, matching the controller.
- `npm run lint` завершается с exit code 0.
- `npm run test:backend` завершается с exit code 0 без live MOEX/network dependency.
- `npm run test:frontend` завершается с exit code 0.
- `npm run build:backend` завершается с exit code 0.
- `npm run build:frontend` завершается с exit code 0.
- `npm run build:docs` завершается с exit code 0 и больше не сообщает о Docusaurus broken links на
`/`.
- `npm run format:check` завершается с exit code 0.
- `apps/frontend/src/api/types.ts` содержит актуальные auth, screener и portfolio paths.
- `docs/openapi/openapi.yaml` содержит актуальные auth, screener и portfolio paths.
- README, AGENTS и Docusaurus docs больше не утверждают, что frontend tests отсутствуют.
- Portfolio docs используют `PATCH /api/v1/portfolios/:id`, что соответствует controller.
## Risks
## Риски
- Swagger decorators may expose DTO gaps that were previously hidden by hand-written frontend types.
Keep the first pass focused on path and schema freshness; defer API-client redesign.
- Live MOEX tests may still fail under network restrictions. That is acceptable only for the
opt-in integration command, not for the default backend test command.
- Regenerating OpenAPI artifacts can produce broad diffs. Review generated changes separately from
hand-written docs changes.
- Swagger decorators могут показать DTO gaps, которые раньше были скрыты hand-written frontend
types. Первый проход должен оставаться сфокусированным на свежести paths и schemas; redesign
API-клиента откладывается.
- Live MOEX tests могут по-прежнему падать в окружениях с network restrictions. Это допустимо только
для opt-in integration command, но не для default backend test command.
- Regenerating OpenAPI artifacts может дать большой diff. Generated changes нужно ревьюить отдельно
от hand-written docs changes.
## Spec Self-Review
## Self-Review спецификации
- Placeholder scan: no placeholder markers or incomplete sections.
- Internal consistency: default tests are offline; live MOEX checks are opt-in.
- Scope check: focused on quality gates, contract snapshots, and docs freshness.
- Ambiguity check: acceptance criteria name concrete commands and contract paths.
- Placeholder scan: placeholder markers и незавершённые sections отсутствуют.
- Internal consistency: default tests остаются offline, live MOEX checks являются opt-in.
- Scope check: scope ограничен quality gates, contract snapshots и актуальностью docs.
- Ambiguity check: acceptance criteria называют конкретные commands и contract paths.