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

12 KiB

Quality Gate, API Contract, and Documentation Refresh Design

Status

Approved for specification on 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:

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

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.

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.

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.

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.

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

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.

Domain Model

Quality Gate

A quality gate is a repeatable command that developers can run without external dependencies unless the command explicitly says otherwise.

Default gates:

  • 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 gates:

  • Live MOEX integration checks. These may use network access and should not run in default unit-test or CI jobs unless explicitly requested.

Contract Source

The authoritative backend contract is the NestJS Swagger document generated from controllers and DTO decorators at /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.

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.

ADR

Decision

Split backend tests into deterministic unit tests and 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.

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 MoexClientService".
  • Contract drift becomes visible because OpenAPI snapshots and frontend generated types are updated as part of this work.

Backend Architecture

Unit Test Boundary

Service tests for SharesService, BondsService, CandlesService, and SecuritiesService should mock MoexClientService and CacheService.

The mocked data should exercise behavior that matters to 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.

Live Integration Test Boundary

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.

The integration command should not be part of the default npm run test:backend command.

OpenAPI Decorators

Controllers that already exist should expose enough Swagger metadata for generated path types:

  • Auth routes: register, login, refresh, logout, me, profile update.
  • Securities routes: search and screener.
  • Portfolio routes: list, create, detail, update, delete, position mutations, analytics.
  • Existing shares, bonds, candles, and 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.

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.

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.

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.

OpenAPI Contract Scope

The synchronized contract should include at least these paths under /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

Update README so quickstart and test sections mention backend, frontend, and docs workspaces.

AGENTS

Update AGENTS to reflect:

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

Docusaurus

Update current onboarding pages:

  • development commands;
  • testing;
  • code generation;
  • frontend overview;
  • frontend routes;
  • frontend API client;
  • 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.

Implementation Phases

Phase 1: Stabilize Default Checks

  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.

Phase 2: Refresh 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.

Phase 3: Refresh Documentation

  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.

Phase 4: Full Verification

Run:

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

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.

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