From a95308762f7207c7062a96a1252f6a7d875bd8c1 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Fri, 19 Jun 2026 08:24:54 +0300 Subject: [PATCH] docs: improve AGENTS.md and README.md --- AGENTS.md | 356 +++++++++++++++++++++++++------------- README.md | 138 ++++++++++++--- apps/backend/.env.example | 32 ++++ 3 files changed, 384 insertions(+), 142 deletions(-) create mode 100644 apps/backend/.env.example diff --git a/AGENTS.md b/AGENTS.md index bd9d0e7..c76f8f8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,21 +1,56 @@ # MoexVibe — Инструкция для агента -## Репозиторий +## Содержание -npm workspaces монорепозиторий: `apps/backend` (NestJS), `apps/frontend` (React + Vite), `apps/docs` (Docusaurus). +- [Обязательный подход к разработке](#обязательный-подход-к-разработке) +- [Процесс разработки](#процесс-разработки) + - [Структура документации](#структура-документации) + - [Назначение документов](#назначение-документов) + - [Правила разработки](#правила-разработки) + - [Определение бага](#определение-бага) + - [Процесс работы над фичей](#процесс-работы-над-фичей) + - [Работа с новыми идеями](#работа-с-новыми-идеями) + - [Работа с существующими фичами](#работа-с-существующими-фичами) + - [Поддержание документации](#поддержание-документации) + - [Поведение AI-агентов](#поведение-ai-агентов) + - [Anti-Loop: лимит на итерации](#anti-loop-лимит-на-итерации) + - [Приоритет источников информации](#приоритет-источников-информации) + - [Git workflow](#git-workflow) + - [Конвенция коммитов](#конвенция-коммитов) + - [Документация и SDD-артефакты](#документация-и-sdd-артефакты) + - [Definition of Done (DoD)](#definition-of-done-dod) +- [Технические регламенты](#технические-регламенты) + - [Правила тестирования](#правила-тестирования) + - [Работа с миграциями Prisma](#работа-с-миграциями-prisma) + - [Правила рефакторинга](#правила-рефакторинга) + - [Политики безопасности](#политики-безопасности) + - [ADR-процесс](#adr-процесс) + - [Правила обновления OpenAPI/типов](#правила-обновления-openapiтипов) + - [Цикл работы над API](#цикл-работы-над-api) +- [Инфраструктура проекта](#инфраструктура-проекта) + - [Команды](#команды) + - [Переменные окружения](#переменные-окружения) +- [Архитектура](#архитектура) + - [Бэкенд](#бэкенд) + - [Фронтенд](#фронтенд) + - [Стиль кода](#стиль-кода) + +--- ## Обязательный подход к разработке - **SDD (Specification-Driven Development)**: перед значимыми изменениями сначала зафиксировать спецификацию нужного масштаба — PRD/цели, доменную модель, ADR, API-контракт, frontend/backend architecture и этапы реализации. Для небольших maintenance-правок достаточно короткого обоснования и acceptance criteria. - **Superpowers**: использовать релевантные Skills при старте задачи. Обычно: brainstorming для уточнения дизайна, systematic-debugging для багов, test-driven-development для feature/bugfix, writing-plans/executing-plans для крупных многошаговых работ, frontend-design для UI, requesting-code-review перед завершением крупных изменений. - **MCP-инструменты**: использовать MCP для анализа, дизайна, работы с API, генерации кода и проверки локального UI, когда это полезно задаче. -- **Visual Companion**: при обсуждении дизайна UI (mockups, макеты, варианты внешнего вида) использовать visual companion в браузере. +- **Visual Companion**: в ходе `brainstorming`, если предстоящие вопросы действительно требуют визуального представления (mockups, wireframes, диаграммы, сравнение вариантов), отдельным сообщением предложить пользователю [Visual Companion](https://github.com/obra/superpowers/blob/main/skills/brainstorming/visual-companion.md). Использовать его только после согласия пользователя и только для тех вопросов, которые понятнее показать, чем описать текстом. Visual Companion — инструмент, а не отдельный режим работы. -# Процесс разработки +--- + +## Процесс разработки Проект использует подход Specification-Driven Development (SDD). -## Структура документации +### Структура документации ```text docs/ @@ -33,23 +68,26 @@ docs/ ├── spec.md ├── plan.md └── tasks.md - + ``` -## Назначение документов -### inbox.md +Полный набор `spec.md`, `plan.md` и `tasks.md` обязателен для новых фич. Исторические feature-каталоги могут быть неполными: отсутствующие артефакты не требуется восстанавливать задним числом, если это не нужно для текущего изменения. + +### Назначение документов + +#### inbox.md Содержит идеи и мысли, которые появились во время работы над проектом. Записи в inbox не являются требованиями и не должны реализовываться напрямую. -### roadmap.md +#### roadmap.md Содержит список запланированных эпиков и фич. Наличие задачи в roadmap не означает, что её нужно немедленно реализовать. -### research/ +#### research/ Содержит результаты исследований и экспериментов. @@ -57,17 +95,18 @@ docs/ Результаты исследований необходимо проверять перед реализацией. -### epics/ +#### epics/ Эпик представляет собой крупную продуктовую возможность или модуль. Эпик может состоять из нескольких фич. -### features/{feature-name}/spec.md +#### features/{feature-name}/spec.md -Описывает ЧТО должно быть реализовано. +Описывает **ЧТО** должно быть реализовано. Спецификация должна содержать: + - цель - требования - ограничения @@ -75,32 +114,32 @@ docs/ Спецификация не должна содержать деталей реализации. -### features/{feature-name}/plan.md +#### features/{feature-name}/plan.md -Описывает КАК будет реализована фича. +Описывает **КАК** будет реализована фича. План может содержать: + - архитектурные решения - API контракты - потоки данных - технический подход -### features/{feature-name}/tasks.md +#### features/{feature-name}/tasks.md Содержит список задач для реализации. Задачи должны быть: + - небольшими - конкретными - независимыми по возможности +### Правила разработки -## Правила разработки +#### Правило 1 - -### Правило 1 - -Нельзя начинать реализацию без спецификации. +Нельзя начинать реализацию новой фичи без спецификации. Если спецификации нет: @@ -109,28 +148,23 @@ docs/ - Уточнить требования. - Только после этого переходить к реализации. -### Правило 2 +#### Правило 2 Реализация должна соответствовать spec.md. Если в процессе разработки выясняется, что требования неполные или ошибочные: -Не изменять поведение системы молча. +- Не изменять поведение системы молча. +- Сначала обновить spec.md и plan.md. +- И только потом продолжать реализацию. -Сначала обновить: -- spec.md -- plan.md - -И только потом продолжать реализацию. - -### Правило 3 +#### Правило 3 Спецификация является источником истины. -Если plan.md противоречит spec.md: -Приоритет имеет spec.md. +Если plan.md противоречит spec.md — приоритет имеет spec.md. -### Правило 4 +#### Правило 4 Не добавлять функциональность, которая отсутствует в спецификации. @@ -139,65 +173,71 @@ docs/ - обновить спецификацию; - либо создать новую фичу. -### Правило 5 +#### Правило 5 -Исправления ошибок можно выполнять напрямую. +Исправления ошибок можно выполнять напрямую. Новая функциональность должна проходить через спецификацию. -Новая функциональность должна проходить через спецификацию. +#### Определение бага +Баг — это поведение системы, противоречащее спецификации, acceptance criteria, API-контракту, зафиксированному тестами поведению или подтверждённому архитектурному инварианту. -## Процесс работы над фичей +Если желаемое поведение нигде не зафиксировано и не следует из существующего контракта или инварианта — это отсутствующая функциональность (new feature), а не баг. -При реализации фичи необходимо: +Классификация: -1) Ознакомиться с эпиком, если он существует. -2) Прочитать spec.md. -3) Прочитать plan.md. -4) Прочитать tasks.md. -5) Выполнять задачи последовательно. -6) Отмечать выполненные задачи. -7) Обновлять plan.md при изменении технических решений. -8) Обновлять spec.md при изменении требований. +- **Есть зафиксированный контракт, поведение не соответствует** → баг (можно чинить напрямую, Правило 5) +- **Нет зафиксированного контракта, требуется новое поведение** → новая фича (нужна спецификация) +- **Spec есть, но в нём неопределённость** → сначала уточнить spec, потом решать, баг это или фича -## Работа с новыми идеями +### Процесс работы над фичей + +При реализации новой фичи необходимо: + +1. Ознакомиться с эпиком, если он существует. +2. Прочитать spec.md. +3. Прочитать plan.md. +4. Прочитать tasks.md. +5. Выполнять задачи последовательно. +6. Отмечать выполненные задачи. +7. Обновлять plan.md при изменении технических решений. +8. Обновлять spec.md при изменении требований. + +Для исторической фичи сначала прочитать все имеющиеся артефакты. Отсутствие старого `plan.md` или `tasks.md` само по себе не блокирует maintenance или исправление бага и не требует создавать их задним числом. Для нового расширения такой фичи сначала подготовить недостающие артефакты в объёме текущего изменения. + +### Работа с новыми идеями Если во время реализации появилась новая идея: -Не реализовывать её автоматически. +Не реализовывать её автоматически. Необходимо определить, является ли она: -Необходимо определить, является ли она: - багом; - улучшением существующей функциональности; - новой фичей. -Если это улучшение или новая фича: +Если это улучшение или новая фича — добавить её в inbox.md или создать отдельную фичу. -Добавить её в: -- inbox.md - -или создать отдельную фичу. - -## Работа с существующими фичами +### Работа с существующими фичами Улучшения существующей функциональности обычно остаются внутри текущего эпика. Пример: +``` Portfolio Dashboard -- История операций -- Пагинация истории операций -- Фильтрация истории операций -- Экспорт истории операций - -Все перечисленные возможности относятся к одному эпику. +├── История операций +├── Пагинация истории операций +├── Фильтрация истории операций +└── Экспорт истории операций +``` Новый эпик создаётся только при появлении новой продуктовой возможности или нового домена. -## Поддержание документации +### Поддержание документации Документация должна соответствовать текущему состоянию проекта. После значимых изменений необходимо обновлять: + - spec.md - plan.md - tasks.md @@ -206,27 +246,40 @@ Portfolio Dashboard Документация не должна отставать от реализации. -## Поведение AI-агентов +### Поведение AI-агентов Перед написанием кода необходимо: -1) Изучить спецификацию фичи. -2) Проверить полноту требований. -3) Найти неоднозначности и противоречия. -4) При необходимости запросить уточнения. -Запрещено: +1. Изучить спецификацию фичи. +2. Проверить полноту требований. +3. Найти неоднозначности и противоречия. +4. При необходимости запросить уточнения. +5. Перед началом реализации агент должен кратко подтвердить понимание задачи и спецификации (одним сообщением). + +**Запрещено:** + - придумывать требования; - додумывать поведение системы; - реализовывать неописанную функциональность. -Если информации недостаточно: -- Остановиться и запросить уточнение вместо того, чтобы делать предположения. +Если информации недостаточно — остановиться и запросить уточнение вместо того, чтобы делать предположения. -## Приоритет источников информации +### Anti-Loop: лимит на итерации + +Если после 3 последовательных неудачных попыток исправить одну и ту же проблему в рамках одной гипотезы симптом не изменился — остановиться и запросить помощь у пользователя. + +Правила: + +- Каждая попытка = один цикл «сформулировал гипотезу → внёс изменение → проверил → тот же симптом сохранился» +- Сбор новой диагностической информации без изменения кода попыткой не считается +- Не начинать 4-ю попытку без явного указания пользователя +- При запросе помощи приложить: что пытался сделать, что пошло не так, последнее состояние кода/логов + +### Приоритет источников информации При возникновении противоречий использовать следующий порядок приоритетов: -1. Текущая задача пользователя. +1. Текущая задача пользователя (она может изменить требования, но соответствующие SDD-артефакты обновляются до реализации). 2. spec.md фичи. 3. plan.md фичи. 4. ADR. @@ -236,70 +289,133 @@ Portfolio Dashboard roadmap.md и inbox.md никогда не являются основанием для реализации функциональности. -## Git workflow +### Git workflow - Для каждой самостоятельной фичи создавать отдельную feature branch и вести разработку внутри неё. - Имя ветки по умолчанию начинать с `codex/`, если пользователь не попросил другой префикс. - Не смешивать независимые фичи в одной ветке. Небольшие связанные docs/chore/test-правки можно держать в той же ветке, если они относятся к текущей задаче. -## Документация и SDD-артефакты +### Конвенция коммитов + +Использовать [Conventional Commits](https://www.conventionalcommits.org/): + +- `feat:` — новая функциональность +- `fix:` — исправление бага +- `chore:` — обслуживание (зависимости, конфиги, CI) +- `docs:` — документация +- `refactor:` — рефакторинг без изменения поведения +- `test:` — добавление или исправление тестов +- `style:` — форматирование, кодстайл (prettier) +- `perf:` — улучшение производительности +- `build:` — изменения сборки и зависимостей +- `ci:` — изменения CI/CD + +Формат: `<тип>(<необязательный scope>): <краткое описание в настоящем времени>` + +Примеры: + +- `feat: add portfolio rebalancing endpoint` +- `fix: handle empty dividend list from MOEX` +- `docs: update API authentication section` + +### Документация и SDD-артефакты - `apps/docs` — единственная опубликованная человекочитаемая документация проекта (Docusaurus). - ADR для опубликованной документации находятся в `apps/docs/docs/adr/`. - OpenAPI source of truth — live Swagger JSON бэкенда на `/api/docs-json`; frontend generated types находятся в `apps/frontend/src/api/types.ts`. -## Команды +### Definition of Done (DoD) -| Команда | Что делает | -|---|---| -| `npm run dev:backend` | Запуск NestJS в режиме watch на :3000 | -| `npm run dev:frontend` | Vite dev-сервер на :5173, проксирует `/api` → :3000 | -| `npm run dev:docs` | Docusaurus dev-сервер | -| `npm run build:backend` | `nest build` | -| `npm run build:frontend` | `tsc -b && vite build` (в две фазы) | -| `npm run build:docs` | `docusaurus build` | -| `npm run test:backend` | `vitest run` (SWC, не ts-jest) | -| `npm run test:frontend` | Frontend Vitest suite | -| `npm run lint` | ESLint для backend и frontend | -| `npm run format` | Prettier для всех `*.{ts,tsx}` | -| `npm run codegen -w apps/frontend` | `openapi-typescript` из локального Swagger → `src/api/types.ts` | +- Все acceptance criteria реализованы +- Тесты проходят +- Lint проходит +- Для новой фичи созданы и обновлены spec/plan/tasks; для исторической фичи обновлены существующие и необходимые для текущего изменения артефакты +- Документация обновлена +- Нет TODO без согласования -Live MOEX integration tests opt-in: `npm run test:integration -w apps/backend`. +--- -Один тест: `npx vitest run path/to/test.spec.ts -w apps/backend` +## Технические регламенты -## Переменные окружения +### Правила тестирования -| Переменная | По умолчанию | Описание | -|---|---|---| -| `PORT` | 3000 | Порт бэкенда | -| `MOEX_BASE_URL` | `https://iss.moex.com/iss` | Endpoint MOEX ISS | -| `MOEX_RATE_LIMIT` | 10 | Запросов/с к MOEX | -| `MOEX_CIRCUIT_BREAKER_THRESHOLD` | 5 | Количество ошибок до открытия circuit breaker | -| `MOEX_CIRCUIT_BREAKER_RESET_SECONDS` | 30 | Время до попытки закрыть circuit breaker | -| `T_BANK_TOKEN` | `''` | Server-side токен T-Bank Invest | -| `T_BANK_BASE_URL` | `invest-public-api.tbank.ru:443` | gRPC endpoint T-Bank Invest | -| `T_BANK_CA_CERT_PATH` | `''` | Путь к PEM root CA для gRPC TLS, если локальная сеть подменяет сертификаты | -| `T_BANK_APP_NAME` | `ksv741.moex-vibe` | Metadata приложения для T-Bank | -| `T_BANK_RATE_LIMIT_PER_SECOND` | 5 | Rate limiter для OperationsService и UsersService (запросов/с) | -| `T_BANK_INSTRUMENTS_RATE_LIMIT` | 20 | Rate limiter для InstrumentsService (запросов/с) | -| `T_BANK_REQUEST_TIMEOUT_MS` | 10000 | Deadline gRPC-запроса (мс) | -| `CACHE_MARKET_DATA_TTL` | 900 | TTL рыночных данных (с) | -| `CACHE_HISTORY_TTL` | 3600 | TTL истории (с) | -| `CACHE_CANDLES_TTL` | 3600 | TTL свечей (с) | -| `CACHE_SECURITY_TTL` | 86400 | TTL спецификации (с) | -| `CACHE_SEARCH_TTL` | 3600 | TTL результатов поиска (с) | -| `CACHE_DIVIDENDS_TTL` | 86400 | TTL дивидендных данных (с) | -| `DATABASE_URL` | `file:./dev.db` | URL SQLite для Prisma | -| `JWT_SECRET` | `dev-jwt-secret-...` | Secret для access token | -| `JWT_REFRESH_SECRET` | `dev-refresh-secret-...` | Secret для refresh token | -| `JWT_ACCESS_EXPIRES` | `15m` | TTL access token | -| `JWT_REFRESH_EXPIRES` | `7d` | TTL refresh token | +- Для новой бизнес-логики → обязательны unit-тесты +- Для API-контрактов → интеграционные тесты +- Не мокать собственный код без необходимости +- В unit-тестах мокать внешние API (MOEX, T-Bank) и Prisma +- При исправлении бага — сначала падающий тест (TDD) +- Тесты писать рядом с основным кодом + +### Работа с миграциями Prisma + +- Никогда не редактировать файлы в `prisma/migrations/` вручную +- После изменения `schema.prisma` → `npm exec -w apps/backend -- prisma migrate dev --name ` +- Изменять существующие миграции допустимо только до их публикации/мержа. После мержа создавать новую миграцию +- Всегда запускать `npm exec -w apps/backend -- prisma generate` после изменения схемы + +### Правила рефакторинга + +- Не выполнять крупный рефакторинг вне рамок задачи +- Допустимы: локальные улучшения, устранение техдолга рядом с изменяемым кодом, исправление архитектурных нарушений +- Запрещено: менять структуру проекта без ADR, переписывать модули без отдельной задачи +- Крупный рефакторинг требует отдельного эпика/фичи + ADR + +### Политики безопасности + +- Запрещено логировать токены, пароли, секреты +- Не отключать guard'ы +- Не хранить секреты в коде, не коммитить .env +- Использовать маскирование при выводе (например, `***`) + +### ADR-процесс + +- Создавать ADR при: выборе новой технологии, изменении архитектуры, изменении API-контрактов, изменении стратегии хранения данных +- ADR должен содержать: Контекст, Рассмотренные варианты, Решение, Последствия + +### Правила обновления OpenAPI/типов + +1. Обновить DTO/Controller на бэкенде +2. Обновить Swagger +3. Запустить `npm run codegen -w apps/frontend` +4. Использовать обновлённые типы из `src/api/types.ts` +5. Никогда не редактировать `types.ts` вручную + +### Цикл работы над API + +Стандартная процедура при любом изменении API-контракта: + +1. **Бэкенд** — описать/обновить DTO и контроллер (NestJS) +2. **Swagger** — убедиться, что документация отдаётся корректно (`/api/docs-json`) +3. **Codegen** — `npm run codegen -w apps/frontend` (генерирует `src/api/types.ts`) +4. **Фронтенд** — использовать обновлённые типы, адаптировать вызовы +5. **Проверка** — убедиться, что `npm run build` проходит в обоих пакетах + +Обновление типов вручную (`types.ts`) запрещено — всегда через codegen. + +--- + +## Инфраструктура проекта + +### Команды + +Основные команды проекта описаны в README.md. + +Перед завершением задачи запускать тесты, lint и build затронутых пакетов. + +### Переменные окружения + +Основные настройки находятся в .env. + +Полный список переменных описан в README.md. + +--- ## Архитектура +### Бэкенд + - **Бэкенд** — единственный клиент MOEX. Фронтенд никогда не обращается к MOEX напрямую. -- Feature-модули: `PrismaModule` (глобальный), `MoexClientModule` (глобальный), `CacheModule` (глобальный), `AuthModule`, `SharesModule`, `BondsModule`, `SecuritiesModule`, `CandlesModule`, `PortfolioModule`, `HealthModule`. +- Актуальная композиция backend-модулей определяется в `apps/backend/src/app.module.ts`; не дублировать динамический список модулей в инструкциях. Опубликованное описание архитектуры находится в `apps/docs/docs/backend/modules.md`. - `MoexClientService` использует p-queue (rate limiter) + circuit breaker (5 ошибок → 30s открыт). - In-memory кеш через `@nestjs/cache-manager`. Путь миграции на Redis описан (см. ADR-002). - Аутентификация: JWT access token (15m, в памяти) + refresh token (7d, httpOnly cookie, bcrypt hash в БД). Глобальный `JwtAuthGuard` (`@Public()` для открытых эндпоинтов). @@ -309,7 +425,7 @@ Live MOEX integration tests opt-in: `npm run test:integration -w apps/backend`. - Ответы API обёрнуты в `{ data: T, meta: { fromCache, cachedAt } }`. - Алиасы: `@/*` → `src/*` в обоих пакетах. -## Фронтенд +### Фронтенд - React 18 + react-router-dom v6 + TanStack Query v5. - `lightweight-charts` v4 для графиков цен. @@ -318,7 +434,7 @@ Live MOEX integration tests opt-in: `npm run test:integration -w apps/backend`. - Конвенция ключей запросов: `['stock', secid]`, `['securities', 'search', query]`, и т.д. - CSS через `styles.css` (CSS custom properties, без CSS-in-JS или Tailwind). -## Стиль кода +### Стиль кода - Prettier: одинарные кавычки, trailing commas, printWidth 100, точки с запятой. - Бэкенд: `const`, PascalCase для модулей/контроллеров/сервисов, DTO в `dto/` внутри каждого модуля. diff --git a/README.md b/README.md index e457e53..dce1318 100644 --- a/README.md +++ b/README.md @@ -2,60 +2,154 @@ Веб-приложение для анализа ценных бумаг Московской биржи (MOEX). -## Tech Stack +## Содержание -- **Backend:** NestJS, TypeScript, OpenAPI (Swagger) -- **Frontend:** React, TypeScript, Vite, TanStack Query, lightweight-charts -- **Docs:** Docusaurus -- **Infrastructure:** Docker, docker-compose +- [О проекте](#о-проекте) +- [Стек технологий](#стек-технологий) +- [Быстрый старт](#быстрый-старт) +- [Docker](#docker) +- [Тестирование](#тестирование) +- [Структура проекта](#структура-проекта) +- [Команды](#команды) +- [Переменные окружения](#переменные-окружения) -## Quick Start +--- + +## О проекте + +npm workspaces монорепозиторий: + +| Пакет | Назначение | +| --------------- | -------------------------------------------------- | +| `apps/backend` | NestJS API (единственная точка доступа к MOEX ISS) | +| `apps/frontend` | React SPA на Vite | +| `apps/docs` | Сайт документации Docusaurus | + +--- + +## Стек технологий + +- **Бэкенд:** NestJS, TypeScript, OpenAPI (Swagger) +- **Фронтенд:** React, TypeScript, Vite, TanStack Query, lightweight-charts +- **Документация:** Docusaurus +- **Инфраструктура:** Docker, docker-compose + +--- + +## Быстрый старт ```bash -# Install dependencies -npm install +# Настройка локального окружения +cp apps/backend/.env.example apps/backend/.env -# Start backend (http://localhost:3000) +# Установка зависимостей и подготовка базы данных +npm install +npm exec -w apps/backend -- prisma migrate dev + +# Запуск бэкенда (http://localhost:3000) npm run dev:backend -# Start frontend (http://localhost:5173) +# Запуск фронтенда (http://localhost:5173) npm run dev:frontend ``` Swagger UI: http://localhost:3000/api/docs +--- + ## Docker ```bash docker compose up --build ``` -- Frontend: http://localhost:80 -- Backend: http://localhost:3000 +- Фронтенд: http://localhost:80 +- Бэкенд: http://localhost:3000 -## Tests +--- + +## Тестирование ```bash npm run test:backend npm run test:frontend ``` -Live MOEX integration checks are opt-in: +Интеграционные тесты с MOEX — опциональны: ```bash npm run test:integration -w apps/backend ``` -## Project Structure +--- + +## Структура проекта ``` apps/ - backend/ — NestJS API (single point of access to MOEX ISS) - frontend/ — React SPA with Vite - docs/ — Docusaurus documentation site + backend/ — NestJS API, единая точка доступа к MOEX ISS + frontend/ — React SPA на Vite + docs/ — сайт документации Docusaurus docs/ - features/ — SDD feature specifications and implementation plans - epics/ — product epics - inbox.md — captured ideas and follow-ups - roadmap.md — planned epics and features + features/ — спецификации и планы реализации (SDD) + epics/ — продуктовые эпики + inbox.md — идеи и заметки + roadmap.md — запланированные эпики и фичи ``` + +--- + +## Команды + +| Команда | Что делает | +| ---------------------------------- | --------------------------------------------------------------------------- | +| `npm run dev:backend` | Запуск NestJS в режиме watch на :3000 | +| `npm run dev:frontend` | Vite dev-сервер на :5173, проксирует `/api` → :3000 | +| `npm run dev:docs` | Docusaurus dev-сервер | +| `npm run build:backend` | `nest build` | +| `npm run build:frontend` | `tsc -b && vite build` (в две фазы) | +| `npm run build:docs` | `docusaurus build` | +| `npm run test:backend` | `vitest run` (SWC, не ts-jest) | +| `npm run test:frontend` | Frontend Vitest suite | +| `npm run lint` | ESLint для backend и frontend | +| `npm run format` | Prettier для всех `*.{ts,tsx}` | +| `npm run codegen -w apps/frontend` | `openapi-typescript` из запущенного локального Swagger → `src/api/types.ts` | + +Интеграционные тесты с MOEX: `npm run test:integration -w apps/backend`. + +Один backend-тест: `npm exec -w apps/backend -- vitest run src/path/to/test.spec.ts` + +--- + +## Переменные окружения + +| Переменная | По умолчанию | Описание | +| ------------------------------------ | -------------------------------- | -------------------------------------------------------------- | +| `PORT` | 3000 | Порт бэкенда | +| `MOEX_BASE_URL` | `https://iss.moex.com/iss` | Адрес MOEX ISS | +| `MOEX_RATE_LIMIT` | 10 | Запросов/с к MOEX | +| `MOEX_CIRCUIT_BREAKER_THRESHOLD` | 5 | Ошибок до открытия circuit breaker | +| `MOEX_CIRCUIT_BREAKER_RESET_SECONDS` | 30 | Секунд до попытки закрыть circuit breaker | +| `T_BANK_TOKEN` | `''` | Токен T-Bank Invest (серверный) | +| `T_BANK_BASE_URL` | `invest-public-api.tbank.ru:443` | gRPC endpoint T-Bank Invest | +| `T_BANK_CA_CERT_PATH` | `''` | Путь к PEM root CA для gRPC TLS | +| `T_BANK_APP_NAME` | `ksv741.moex-vibe` | Имя приложения для T-Bank | +| `T_BANK_RATE_LIMIT_PER_SECOND` | 5 | Rate limiter для OperationsService и UsersService (запросов/с) | +| `T_BANK_INSTRUMENTS_RATE_LIMIT` | 20 | Rate limiter для InstrumentsService (запросов/с) | +| `T_BANK_REQUEST_TIMEOUT_MS` | 10000 | Таймаут gRPC-запроса (мс) | +| `CACHE_MARKET_DATA_TTL` | 900 | TTL рыночных данных (с) | +| `CACHE_HISTORY_TTL` | 3600 | TTL истории (с) | +| `CACHE_CANDLES_TTL` | 3600 | TTL свечей (с) | +| `CACHE_SECURITY_TTL` | 86400 | TTL спецификации (с) | +| `CACHE_SEARCH_TTL` | 3600 | TTL результатов поиска (с) | +| `CACHE_DIVIDENDS_TTL` | 86400 | TTL дивидендных данных (с) | +| `CACHE_TBANK_ACCOUNTS_TTL` | 3600 | TTL брокерских счетов T-Bank (с) | +| `CACHE_TBANK_PORTFOLIO_TTL` | 60 | TTL брокерского портфеля T-Bank (с) | +| `CACHE_TBANK_OPERATIONS_TTL` | 300 | TTL брокерских операций T-Bank (с) | +| `CACHE_TBANK_POSITIONS_TTL` | 60 | TTL брокерских позиций T-Bank (с) | +| `CACHE_TBANK_INSTRUMENT_TTL` | 86400 | TTL инструментов T-Bank (с) | +| `DATABASE_URL` | `file:./dev.db` | URL SQLite для Prisma | +| `JWT_SECRET` | `dev-jwt-secret-...` | Secret для access token | +| `JWT_REFRESH_SECRET` | `dev-refresh-secret-...` | Secret для refresh token | +| `JWT_ACCESS_EXPIRES` | `15m` | TTL access token | +| `JWT_REFRESH_EXPIRES` | `7d` | TTL refresh token | diff --git a/apps/backend/.env.example b/apps/backend/.env.example new file mode 100644 index 0000000..1f90f79 --- /dev/null +++ b/apps/backend/.env.example @@ -0,0 +1,32 @@ +PORT=3000 +DATABASE_URL=file:./dev.db + +MOEX_BASE_URL=https://iss.moex.com/iss +MOEX_RATE_LIMIT=10 +MOEX_CIRCUIT_BREAKER_THRESHOLD=5 +MOEX_CIRCUIT_BREAKER_RESET_SECONDS=30 + +T_BANK_TOKEN= +T_BANK_BASE_URL=invest-public-api.tbank.ru:443 +T_BANK_CA_CERT_PATH= +T_BANK_APP_NAME=ksv741.moex-vibe +T_BANK_RATE_LIMIT_PER_SECOND=5 +T_BANK_INSTRUMENTS_RATE_LIMIT=20 +T_BANK_REQUEST_TIMEOUT_MS=10000 + +CACHE_MARKET_DATA_TTL=900 +CACHE_HISTORY_TTL=3600 +CACHE_CANDLES_TTL=3600 +CACHE_SECURITY_TTL=86400 +CACHE_SEARCH_TTL=3600 +CACHE_DIVIDENDS_TTL=86400 +CACHE_TBANK_ACCOUNTS_TTL=3600 +CACHE_TBANK_PORTFOLIO_TTL=60 +CACHE_TBANK_OPERATIONS_TTL=300 +CACHE_TBANK_POSITIONS_TTL=60 +CACHE_TBANK_INSTRUMENT_TTL=86400 + +JWT_SECRET=dev-jwt-secret-change-in-production +JWT_REFRESH_SECRET=dev-refresh-secret-change-in-production +JWT_ACCESS_EXPIRES=15m +JWT_REFRESH_EXPIRES=7d