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

327 lines
12 KiB
Markdown

# 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:
```bash
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.