# WealthLedger Локальное приложение для портфеля T-Bank, операций, дохода и будущих выплат, а также ручного учёта банковских карт и расходов. [Обзор продукта](https://git.personal.ksv741.ru/WealthLedger/docs/src/commit/c557af4ea51cd3c578d0755e909e62e06462b5bc/overview.md) и [документация системы](https://git.personal.ksv741.ru/WealthLedger/docs/src/commit/c557af4ea51cd3c578d0755e909e62e06462b5bc/README.md). ## Структура workspace Workspace состоит из пяти независимых Git-репозиториев. Root — репозиторий `WealthLedger/main`; вложенные checkout не являются submodules. | Путь от root | Репозиторий Gitea | Назначение | | --- | --- | --- | | `.` | `WealthLedger/main` | Вход в workspace, инструкции и правила root tracking | | `frontend/` | `WealthLedger/frontend` | [React/Vite UI](https://git.personal.ksv741.ru/WealthLedger/frontend/src/commit/9f7e342333b80bfacfd5bc394a2dcd0613d33ff3/README.md) | | `backend/` | `WealthLedger/backend` | [NestJS API, Prisma и SQLite](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/README.md) | | `docs/` | `WealthLedger/docs` | [Объяснение системы](https://git.personal.ksv741.ru/WealthLedger/docs/src/commit/c557af4ea51cd3c578d0755e909e62e06462b5bc/README.md) | | `specs/` | `WealthLedger/specs` | [Требования и OpenSpec](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/README.md) | ### Получение checkout Нужны Git и SSH-доступ к Gitea на порту 2222. Из родительского каталога, где ещё нет `WealthLedger`, выполните: ```bash git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/main.git WealthLedger cd WealthLedger git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/frontend.git frontend git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/backend.git backend git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/docs.git docs git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/specs.git specs ``` Для существующего workspace клонируйте только отсутствующие checkout в пустые каталоги. Проверяйте состояние каждого repo отдельно, например `git -C frontend status`. Обновление main не обновляет соседние repos; общего lockfile revisions нет. Такая раскладка удобна для совместной работы, но каждый checkout можно использовать отдельно. ### Что хранится в main Root отслеживает входные документы, собственные engineering conventions и исторический migration inventory в `.ai/`, npm/release-конфигурацию, changelog, Compose configuration, безопасные env examples и один CI workflow с commitlint. Точный allowlist — в `.gitignore`. Остальные root-пути игнорируются по умолчанию: вложенные repos, `.env`, базы и WAL, импорты выписок, PDF, `references/`, `design/`, `todo/` и локальные настройки инструментов. Новый общий файл включается отдельной правкой allowlist после проверки содержимого. Перед commit смотрите `git diff --cached --name-status` в нужном repo. Не используйте `git add -f` для обхода границ root. Ignore не защищает уже отслеживаемые файлы и не меняет правила внутри вложенных repos. Не запускайте очистку workspace через `git clean -fdx`: ignored-пути содержат локальные данные. Правила tracking не удаляют файлы и вложенные `.git`. ## Запуск через Docker Compose Нужны Docker Engine и Compose >= 2.24.4, а для development — checkout `frontend/` и `backend/` рядом с root. Компоненты собираются независимо: ```bash docker compose --env-file .env.development.example \ -f compose.yaml -f compose.development.yaml up -d --build --wait --wait-timeout 180 ``` Откройте `http://localhost:5173`: Vite HMR и `/api/` используют один origin, Nest работает в watch mode. Host `node_modules` и `.env` не монтируются. Данные development хранятся отдельно в named volume `development-data` проекта `wealthledger-dev`; обычные restart/down их сохраняют. Изменение dependencies/config требует rebuild. Production использует отдельный [репозиторий deploy](https://git.personal.ksv741.ru/WealthLedger/deploy): его Git-тег закрепляет пару images, а `./deploy.sh vX.Y.Z` выполняет обновление. Рабочие данные, сертификат T-Bank и постоянные ключи находятся вне checkout. Только frontend публикует `127.0.0.1:8080`; серверный Caddy направляет туда весь домен. Backend port остаётся внутренним. Корневой Compose сохраняется для development. Пошаговая процедура установки, обновления и восстановления — README `deploy`; архитектурные границы — [документация](https://git.personal.ksv741.ru/WealthLedger/docs), страница `architecture/deployment.md`. Перед backend update обязательны остановка, backup и успешная migration. Image rollback не восстанавливает старую базу. Публикация component images принадлежит их Gitea workflows; root CI остаётся только commitlint. ## Подготовка и запуск Нужны nvm и Node из `.nvmrc` каждого npm-repo (сейчас 24.21.0, npm 11.19). Во всех пяти репозиториях отдельно выполните `nvm install`, `nvm use --silent`, `npm ci`. В root и specs npm нужен для release-it и проверки сообщений коммитов. После смены major Node переустановите native dependencies через `npm ci`. Разрешения install scripts заданы в `package.json` соответствующего repo. Для нового backend создайте `.env` по [backend README](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/README.md), замените оба placeholder-секрета и проверьте `DATABASE_URL`. Существующий `.env` сохраняйте. Из backend: ```bash nvm use --silent npm run build npx prisma migrate deploy npm run start:dev ``` Build генерирует Prisma client. Перед миграцией существующей базы сохраните согласованный backup и ключ шифрования; процедуру и ограничения отката смотрите в [описании хранения](https://git.personal.ksv741.ru/WealthLedger/docs/src/commit/c557af4ea51cd3c578d0755e909e62e06462b5bc/architecture/containers.md#сохранение-и-восстановление-данных). Известная ошибка fresh migration при `RUST_LOG=warn/error` устранена в `backend/prisma.config.ts`: CLI удаляет унаследованную переменную. Используйте штатный `prisma migrate deploy` из backend; прежний Prisma blocker снят. [Подробности и границы проверки](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/README.md#реальная-sqlite-и-сохранность-данных). В другом терминале подготовьте `.env` по [frontend README](https://git.personal.ksv741.ru/WealthLedger/frontend/src/commit/9f7e342333b80bfacfd5bc394a2dcd0613d33ff3/README.md), затем из frontend: ```bash nvm use --silent npm run dev ``` Стандартные адреса: frontend `http://localhost:5173`, API `http://localhost:3000`. Origin backend и адрес API frontend должны совпадать с выбранными адресами. T-Bank token вводится через настройки приложения; без него доступны вход и ручной банковский учёт. Для вымышленных UI-примеров выполните `npm run dev:catalog` из frontend. ### OpenSpec OpenSpec не нужен для запуска приложения и применяется по явному запросу. Specs использует Node из своей `.nvmrc`; проверенная версия CLI — 1.10.0. Store `wealth-ledger-specs` расположен в `specs/openspec/`. [Работа с OpenSpec](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/AGENTS.md), [команды validation](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/README.md#проверка). ## Проверки Перед npm-командами активируйте `.nvmrc` соответствующего repo. | Где | Команда | Что проверяет | | --- | --- | --- | | root | `npm exec --no -- commitlint --strict --from --to ` | Формат сообщений коммитов | | root | `git diff --check` | Whitespace в изменениях root | | frontend | `npm run verify` | Типы, lint, тесты, зависимости, OpenAPI snapshot и сборки | | backend | `npm run verify` | Lint, типы, unit tests и build | | backend | `npm run test:e2e` | HTTP/SQLite suites и локальный OpenAPI artifact | | docs | `npm run verify` | Markdown, относительные ссылки и diff | Root CI выполняет только commitlint: проверяет сообщения коммитов и заголовок PR. Allowlist root проверяется вручную по staged paths. Backend e2e использует временные базы; verify отдельно не доказывает HTTP/DB-сценарии или доступность T-Bank. Полные команды и ограничения принадлежат README [frontend](https://git.personal.ksv741.ru/WealthLedger/frontend/src/commit/9f7e342333b80bfacfd5bc394a2dcd0613d33ff3/README.md#проверка) и [backend](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/README.md#проверка). Для изменения проекта начните с [AGENTS](AGENTS.md). ## Релизы и ветки Все пять репозиториев выпускаются независимо. Первый релиз — `0.1.0`; версия в `package.json` и lockfile соответствует последнему принятому тегу `vX.Y.Z`. Root-репозиторий называется `main`, его ветки — `main` и `develop`. `main` хранит принятые релизы, `develop` — интеграцию разработки. Новая задача: отдельная ветка от свежего `develop`, затем PR в `develop`. Для веток агента используется `codex/`; также допустимы `feature/` и `fix/`. В `main` напрямую не пушить. Обычные PR можно squash-merge; релизные PR и обратную синхронизацию `main` с `develop` сливать с сохранением истории. Commits и заголовки PR — Conventional Commits. `feat:` повышает minor, `fix:`/`perf:` — patch, `!` или `BREAKING CHANGE:` — major, в том числе до 1.0. `docs:`, `spec:`, `chore:`, `build:`, `ci:`, `refactor:`, `test:`, `style:` и `revert:` дают patch при выпуске. `chore(release):` — служебная запись, исключённая из changelog и рекомендации версии. Release-it не запускается автоматически после каждого commit. Номер связанной issue можно добавить в заголовок. ### Подготовка релиза 1. Обновить `main`, `develop` и теги командой `git fetch origin --tags`. Проверить, что текущий `develop` содержит последний релиз из `main`. Создать `release/` от проверенного `develop` и выполнить `npm ci`. 2. Проверить локальные входы и публичные artifacts выпускаемого репозитория. Совместимость развёрнутых участников согласовать отдельно через публичные контракты; CI не скачивает соседние checkout и не требует их SHA. 3. Выполнить `npm run release:preview`. Проверить номер и changelog, затем `npm run release:prepare`. Команда создаёт `chore(release): X.Y.Z`, обновляет `package.json`, lockfile и `CHANGELOG.md`; теги и push не выполняет. В root встроенные проверки release-it контролируют ветку, чистое дерево и наличие коммитов. Теги и соответствие версии последнему принятому тегу проверяются вручную; уже подготовленную версию повторно не повышать. 4. Проверить diff релизного коммита и штатные gates. Отправить только релизную ветку: `git push -u origin HEAD`. Открыть PR в `main` с заголовком `chore(release): X.Y.Z`. После зелёных обязательных проверок (`commits` в root; `verify`, `security`, `commits` в остальных repo) выполнить **fast-forward-only merge**. Если `main` изменился, сначала согласовать историю и повторить проверку кандидата; не обходить защиту. 5. После merge получить `main` и убедиться, что его HEAD — проверенный релизный коммит, версия и lockfile совпадают. На этом SHA создать аннотированный тег: `git tag -a vX.Y.Z -m "Release X.Y.Z"`, затем отправить только этот тег: `git push origin refs/tags/vX.Y.Z`. Повторно release-it на `main` не запускать: он уже подготовил версию. 6. Через PR `main → develop` вернуть релизный коммит в разработку без squash и rebase. Убедиться, что `develop` содержит тег. После первого выпуска `develop` создаётся непосредственно от релизного SHA. Перед публикацией тегов сравнить local SHA с удалённым `main`; PR и проверки должны относиться к этому кандидату. Опубликованные теги не перемещать. При сбое после merge продолжить с создания отсутствующего тега, без нового bump. При сбое до merge исправить релизную ветку и заново проверить кандидат; подготовленную версию и changelog не повышать второй раз. Пять репозиториев не имеют общей атомарной публикации: завершённость проверяется отдельно по каждому. Первый выпуск задаётся явно: `npm run release:prepare -- 0.1.0` из `release/0.1.0`. Начальные `0.0.0` — bootstrap-состояние до первого тега. Исторические неконвенциональные commits не переписываются; первый changelog требует просмотра человеком. Дальнейшие версии выбираются по commits. ### Hotfix, проверки и защита Срочный fix начинается от `main`, проходит проверки и релизный PR из `release/hotfix-` в `main`, затем обязательно возвращается в `develop`. Если ломается публичный контракт, major сохраняется и для hotfix. Каждый CI использует только свой checkout. Backend генерирует OpenAPI без сервера, сверяет генератор с configured app и не хранит JSON в Git; frontend проверяет types по входному snapshot. Docs проверяет внутренние ссылки; внешние источники даются как справочные веб-ссылки. Обновление API artifact потребителя — отдельное действие. Зелёные локальные gates и порядок публикации не доказывают совместимость развёрнутых версий. Процедуры выпуска находятся также в README каждого repo; доступ к root для выпуска другого репозитория не требуется. В Gitea для `main` и `develop` нужны запрет прямого push и force-push, обязательные проверки: в root только `commits`, в остальных repo — `verify`, `security`, `commits`; также нужен запрет обхода правил администратором. Требование отдельного одобрения review не вводится для разработки одним владельцем. Ветка по умолчанию — `develop`; Renovate тоже отправляет PR в `develop`. Теги `v*` защищены, создание разрешается владельцу релиза; их удаление или перенос не входит в обычный процесс. В root нет собственного test/verify runner и release hooks. Release-it и commitlint используются напрямую. Остальные репозитории сохраняют свои gates. Если в защите веток root ранее были обязательными `verify` и `security`, их нужно убрать из required checks в Gitea; YAML не меняет настройки сервера. Npm publishing, автоматический deploy и карточки Gitea Releases не включены. Граница выпуска — принятый коммит, changelog и Git-тег.