diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4ba913c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,17 @@ +# Docs + +## Назначение + +Репозиторий постоянной документации WealthLedger. Функциональные изменения планируются в `../specs/openspec` до реализации; docs фиксирует согласованные и фактически реализованные решения. + +## Проверка + +```bash +git status --short +``` + +## Границы + +- `adr/` - долгоживущие решения, `architecture/` - устройство системы, `development/` - процесс разработки, `features/` - фактическое поведение завершенных фич. +- Для диаграмм использовать Mermaid в Markdown. Feature-документация описывает пользовательский поток, API-сценарий и ограничения. +- Не хранить OpenSpec-артефакты, код приложений или секреты; требования и task-план остаются в `../specs/openspec`. diff --git a/adr/001-prisma-sqlite-local-mvp.md b/adr/001-prisma-sqlite-local-mvp.md new file mode 100644 index 0000000..1d9b557 --- /dev/null +++ b/adr/001-prisma-sqlite-local-mvp.md @@ -0,0 +1,15 @@ +# 001. Prisma и SQLite для локального MVP + +**Status:** Accepted, baseline decision + +## Context + +MVP нужен воспроизводимый локальный доступ к данным без инфраструктуры развёртывания. Доменные таблицы и миграции на baseline отсутствуют. + +## Decision + +Backend использует Prisma с SQLite из конфигурации окружения. Первые доменные таблицы и миграции появятся в соответствующем будущем OpenSpec change. + +## Consequences + +Локальный запуск прост и типизированный доступ к данным готов заранее. SQLite не считается решением для production-развёртывания; его замена потребует отдельного ADR и change. diff --git a/adr/002-nest-generated-openapi-contract.md b/adr/002-nest-generated-openapi-contract.md new file mode 100644 index 0000000..0d7a5d2 --- /dev/null +++ b/adr/002-nest-generated-openapi-contract.md @@ -0,0 +1,15 @@ +# 002. OpenAPI, генерируемый NestJS, как контракт API + +**Status:** Accepted, baseline decision + +## Context + +Ручные frontend-типы и описания маршрутов расходятся с backend и создают дублирование. + +## Decision + +NestJS генерирует OpenAPI из контроллеров и DTO для API с префиксом `/api/v1`. Frontend локальной воспроизводимой командой генерирует и хранит API-клиент в своем репозитории; runtime использует только этот клиент, а не OpenAPI endpoint. + +## Consequences + +Изменение HTTP-контракта требует регенерации клиента. Swagger/OpenAPI публикуется для локальной разработки и не является runtime-зависимостью frontend. diff --git a/adr/003-tbank-server-side-grpc-boundary.md b/adr/003-tbank-server-side-grpc-boundary.md new file mode 100644 index 0000000..c02e532 --- /dev/null +++ b/adr/003-tbank-server-side-grpc-boundary.md @@ -0,0 +1,21 @@ +# 003. Серверная gRPC-граница T-Bank + +**Status:** Accepted, baseline decision + +## Context + +T-Bank требует секретов и внешняя интеграция должна быть управляемой, наблюдаемой и независимой от браузера. + +## Decision + +Только backend обращается к T-Bank через выделенную gRPC-границу. Frontend вызывает только собственный HTTP API и никогда не получает T-Bank credentials или gRPC-клиент. + +```mermaid +flowchart LR + F[Frontend] --> B[Backend API] + B --> T[T-Bank gRPC] +``` + +## Consequences + +Контроль секретов, повторов и лимитов централизован на сервере. Реализация boundary будет добавлена будущим OpenSpec change подключения T-Bank. diff --git a/adr/004-encrypted-per-user-tbank-token.md b/adr/004-encrypted-per-user-tbank-token.md new file mode 100644 index 0000000..b3e9e53 --- /dev/null +++ b/adr/004-encrypted-per-user-tbank-token.md @@ -0,0 +1,15 @@ +# 004. Шифрование T-Bank токена пользователя + +**Status:** Accepted, baseline decision + +## Context + +Токен T-Bank является секретом пользователя и не должен быть доступен браузеру или сохранён в открытом виде. + +## Decision + +Для каждого пользователя backend хранит один токен, зашифрованный ключом `TOKEN_ENCRYPTION_KEY`. API не возвращает токен frontend; расшифровка допустима только серверу непосредственно для вызова T-Bank. + +## Consequences + +Ключ обязателен только в server environment и не логируется. Ротация ключей, схема хранения и реализация будут добавлены в будущем change подключения T-Bank. diff --git a/adr/005-tbank-upstream-resilience.md b/adr/005-tbank-upstream-resilience.md new file mode 100644 index 0000000..f7ffe7a --- /dev/null +++ b/adr/005-tbank-upstream-resilience.md @@ -0,0 +1,15 @@ +# 005. Устойчивость к ограничениям T-Bank upstream + +**Status:** Accepted, baseline decision + +## Context + +Внешний API имеет ограничения и временные ошибки; параллельные запросы пользователей не должны их обходить. + +## Decision + +Backend применяет глобальный конфигурируемый лимитер в 5 запросов в секунду к T-Bank, ограниченные временные повторы и повторы для `429`. In-memory TTL-кэш хранит данные 30 секунд, а инструменты не менее одного дня. + +## Consequences + +Лимит действует на экземпляр backend и кэш не переживает перезапуск. Распределённые лимиты, кэш и точные параметры retry будут рассмотрены при появлении нескольких экземпляров или подтвержденных требований upstream. diff --git a/adr/006-auth-session-policy.md b/adr/006-auth-session-policy.md new file mode 100644 index 0000000..963bed1 --- /dev/null +++ b/adr/006-auth-session-policy.md @@ -0,0 +1,15 @@ +# 006. Политика access и refresh сессий + +**Status:** Accepted, baseline decision + +## Context + +Клиенту нужна короткая авторизация без передачи долгоживущего секрета JavaScript-коду. + +## Decision + +Access token живёт 15 минут только в памяти frontend. Rotating refresh token живёт 7 дней и передаётся в cookie `httpOnly`, `SameSite=Lax`; сервер заменяет refresh token при обновлении сессии. + +## Consequences + +Перезагрузка страницы требует обновления access token через cookie-сессию. Полная реализация сессий, хранилища и отзыва будет добавлена change авторизации. diff --git a/adr/007-react-query-fetch-policy.md b/adr/007-react-query-fetch-policy.md new file mode 100644 index 0000000..a581939 --- /dev/null +++ b/adr/007-react-query-fetch-policy.md @@ -0,0 +1,15 @@ +# 007. Политика запросов и кэша React Query + +**Status:** Accepted, baseline decision + +## Context + +Автоматические повторные запросы могут создавать лишнюю нагрузку на ограниченный T-Bank upstream. + +## Decision + +React Query запрашивает серверные данные только при открытии соответствующего экрана. Refetch по возврату фокуса отключён, обновление запускается пользователем вручную; backend TTL-кэш остаётся защитой от дублирующих запросов. + +## Consequences + +Пользователь может видеть данные до ручного обновления или следующего открытия экрана. Live-обновления и иные триггеры появятся только при подтверждённой продуктовой необходимости. diff --git a/adr/README.md b/adr/README.md new file mode 100644 index 0000000..656e0fd --- /dev/null +++ b/adr/README.md @@ -0,0 +1,3 @@ +# ADR + +Здесь фиксируются долгоживущие технические решения. Новый ADR описывает контекст, решение и последствия; заменяемое решение получает новый ADR со ссылкой на прежний. diff --git a/architecture/README.md b/architecture/README.md new file mode 100644 index 0000000..a17ddf8 --- /dev/null +++ b/architecture/README.md @@ -0,0 +1,3 @@ +# Architecture + +Здесь описывается фактическое устройство системы, общие границы компонентов и интеграций. Диаграммы Mermaid добавляются, когда они проясняют взаимодействие. diff --git a/development/README.md b/development/README.md new file mode 100644 index 0000000..8e34892 --- /dev/null +++ b/development/README.md @@ -0,0 +1,3 @@ +# Development + +Здесь размещаются устойчивые правила разработки, локальной проверки и поставки. Требования и планы изменений остаются в `../specs/openspec`. diff --git a/features/README.md b/features/README.md new file mode 100644 index 0000000..3c40fb8 --- /dev/null +++ b/features/README.md @@ -0,0 +1,3 @@ +# Features + +Здесь документируется фактическое поведение завершенных пользовательских фич: пользовательский поток, API-сценарий и ограничения. Не реализованные возможности сюда не добавляются.