moex-vibe/docs/superpowers/specs/2026-06-14-quality-gate-contract-docs-design.md

17 KiB
Raw Permalink Blame History

Дизайн стабилизации quality gate, API-контракта и документации

Статус

Одобрено для спецификации 2026-06-14.

PRD

Проблема

В MoexVibe накопился координационный технический долг между тестами, сгенерированными контрактами и документацией. Приложение всё ещё собирается, но стандартный backend quality gate сейчас нельзя считать надёжным:

  • 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 на /.

Из-за этого следующие задачи делать медленнее: разработчику неочевидно, какой вывод команд важен, какой API-контракт актуален и почему backend-тесты падают: из-за поведения приложения или из-за сетевой зависимости.

Цели

  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.

Не входит в задачу

  • Пользовательские feature-изменения.
  • Глубокий рефакторинг PortfolioService или MoexClientService.
  • Переход frontend API-клиента на полностью сгенерированный клиент.
  • Redis, изменение схемы БД, redesign auth-модели или portfolio analytics.
  • Миграция CI-провайдера.

Текущие находки

Проходящие проверки

  • npm run test:frontend проходит: 22 файла, 95 тестов.
  • npm run format:check проходит.
  • npm run build:backend проходит.
  • npm run build:frontend проходит.
  • npm run build:docs успешно генерирует статические файлы.

Падающие или шумные проверки

  • 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
    • похожие service specs для shares и bonds тоже зависят от live MOEX-доступа.
  • npm run build:docs предупреждает, что многие страницы ссылаются на /.

Устаревшая документация и контрактные артефакты

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

Доменная модель

Quality Gate

Quality gate: это повторяемая команда, которую разработчик может запускать без внешних зависимостей, если сама команда явно не говорит обратного.

Стандартные проверки:

  • npm run lint
  • npm run test:backend
  • npm run test:frontend
  • npm run build:backend
  • npm run build:frontend
  • npm run build:docs
  • npm run format:check

Opt-in проверки:

  • Live MOEX integration checks. Они могут требовать network access и не должны запускаться в стандартных unit tests или CI jobs без явного запроса.

Источник API-контракта

Авторитетный backend contract: NestJS Swagger document, который генерируется из controllers и DTO decorators по /api/docs-json.

Сгенерированные или синхронизированные артефакты:

  • docs/openapi/openapi.yaml: checked-in человекочитаемый snapshot.
  • apps/frontend/src/api/types.ts: сгенерированные TypeScript path и schema types.
  • Docusaurus API pages: поясняющая документация, но не канонический machine contract.

Источник документации

Документация должна описывать текущее состояние репозитория, а не исторический план реализации. Superpowers specs и plans остаются историей проекта. README, AGENTS и Docusaurus pages являются актуальной onboarding-поверхностью.

ADR

Решение

Разделить backend tests на детерминированные unit tests и opt-in live MOEX integration tests.

Обоснование

Стандартная backend test command сейчас смешивает unit-поведение и доступность внешней сети. Это делает failures неоднозначными и порождает шумные Vitest serialization errors, когда Axios возвращает rejection с non-cloneable configuration fields. Unit tests должны проверять логику приложения на контролируемых fixtures. Live MOEX tests полезны, но должны быть отдельной явно названной командой с понятным требованием к окружению.

Последствия

  • npm run test:backend становится стабильной offline-командой.
  • Live MOEX coverage остаётся доступным через отдельную integration command.
  • Часть существующих specs изменится с "real MOEX smoke test" на "service behavior with mocked MoexClientService".
  • Contract drift станет видимым, потому что OpenAPI snapshots и frontend generated types будут обновлены в рамках этой работы.

Backend Architecture

Граница unit tests

Service tests для SharesService, BondsService, CandlesService и SecuritiesService должны mock'ать MoexClientService и CacheService.

Mocked data должны проверять поведение, важное для MoexVibe:

  • нормализованные 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 tests

Live MOEX checks должны быть изолированы в *.integration.spec.ts files или эквивалентном явном test path. Они должны запускаться только через отдельную команду, например npm run test:integration -w apps/backend, и должны документировать, что для них требуется network access.

Integration command не должна входить в стандартный npm run test:backend.

OpenAPI decorators

Существующие controllers должны отдавать достаточно Swagger metadata для generated path types:

  • Auth routes: register, login, refresh, logout, me, profile update.
  • Securities routes: search и screener.
  • Portfolio routes: list, create, detail, update, delete, position mutations, analytics.
  • Существующие shares, bonds, candles и health routes.

В реализации нужно предпочитать существующие DTO и response DTO. Если для response нет DTO и добавление полного DTO слишком раздувает первый проход, можно использовать минимальные response decorators без изменения runtime behavior.

Frontend Architecture

Generated Types

apps/frontend/src/api/types.ts должен быть перегенерирован из текущего backend Swagger JSON после того, как backend Swagger metadata будет покрывать актуальные routes.

Существующие hand-written responses.ts и API wrapper modules остаются на месте в этом эпике. Цель: свежесть контракта, а не полный rewrite клиента.

Tests

Frontend tests уже существуют и проходят. Этот эпик не должен переписывать frontend testing architecture. Если API response types изменятся, frontend tests нужно обновлять только там, где перегенерированный contract выявит реальное несоответствие.

OpenAPI Contract Scope

Синхронизированный contract должен включать минимум эти paths под /api/v1:

  • GET /health
  • POST /auth/register
  • POST /auth/login
  • POST /auth/refresh
  • POST /auth/logout
  • GET /auth/me
  • PATCH /auth/me
  • GET /securities/search
  • GET /securities/screener
  • GET /securities/shares/{secid}
  • GET /securities/shares/{secid}/marketdata
  • GET /securities/shares/{secid}/dividends
  • GET /securities/shares/{secid}/history
  • GET /securities/shares/{secid}/candles
  • GET /securities/bonds/{secid}
  • GET /securities/bonds/{secid}/marketdata
  • GET /securities/bonds/{secid}/history
  • GET /securities/bonds/{secid}/candles
  • GET /portfolios
  • POST /portfolios
  • GET /portfolios/{id}
  • PATCH /portfolios/{id}
  • DELETE /portfolios/{id}
  • POST /portfolios/{id}/positions
  • PATCH /portfolios/{id}/positions/{positionId}
  • DELETE /portfolios/{id}/positions/{positionId}
  • GET /portfolios/{id}/analytics

Documentation Architecture

README

Обновить README так, чтобы quickstart и test sections упоминали backend, frontend и docs workspaces.

AGENTS

Обновить AGENTS:

  • apps/docs является частью workspace.
  • npm run lint запускает backend и frontend lint.
  • frontend tests существуют.
  • pre-commit checks существуют через Husky и lint-staged.
  • CI существует в .gitea/workflows/ci.yml.

Docusaurus

Обновить текущие onboarding pages:

  • development commands;
  • testing;
  • code generation;
  • frontend overview;
  • frontend routes;
  • frontend API client;
  • backend API;
  • backend portfolio.

Исправить Docusaurus config или docs links так, чтобы npm run build:docs больше не сообщал о broken links на /. Отдельное update-check warning про permissions в /Users/ksv741/.config является внешним к репозиторию и в этот эпик не входит.

Этапы реализации

Этап 1: стабилизировать стандартные проверки

  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.

Этап 2: обновить contract artifacts

  1. Добавить или завершить Swagger metadata для актуальных routes.
  2. Перегенерировать apps/frontend/src/api/types.ts.
  3. Синхронизировать docs/openapi/openapi.yaml с текущим contract.
  4. Проверить, что generated paths включают auth, screener и portfolio routes.

Этап 3: обновить документацию

  1. Обновить README и AGENTS.
  2. Обновить Docusaurus development, frontend, backend и portfolio pages.
  3. Исправить Docusaurus broken / link warning.
  4. Проверить npm run build:docs.

Этап 4: полная проверка

Запустить:

npm run lint
npm run test:backend
npm run test:frontend
npm run build:backend
npm run build:frontend
npm run build:docs
npm run format:check

Acceptance Criteria

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

Риски

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

Self-Review спецификации

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