26 KiB
Аудит качества WealthLedger
Дата: 2026-08-13
Обновление: 2026-08-14 — повторная проверка находок после доработок align-frontend-foundation и align-frontend-ui-patterns. Статус каждой находки помечен: [done] закрыто, [partial] частично, [open] не тронуто.
Статус: снимок текущей рабочей копии; исправления и OpenSpec-артефакты не создавались.
Цель и охват
Проведён тщательный аудит frontend, backend, specs, docs, корневых файлов координации и .opencode. Папка references/ исключена. Оценивались качество кода, архитектура, безопасность, обработка ошибок, целостность данных, производительность, accessibility, качество сценариев тестирования, документация, OpenSpec и артефакты для AI-агентов.
Текущая рабочая копия является источником фактов. История Git использовалась только для контекста жизненного цикла OpenSpec. Проценты и пороги test coverage намеренно не оценивались.
Методика и ограничения
Аудит сопоставляет локальные правила из AGENTS.md, OpenSpec, feature docs, ADR и фактический код. Проверялись критичные цепочки: регистрация и сессии, transport API, подключение T-Bank, счета и портфель, а также путь «спецификация -> реализация -> документация -> инструкция агенту».
Ограничения:
- Не проводились нагрузочные тесты, анализ production-конфигурации, live-проверки T-Bank, TLS/proxy и multi-instance развёртывания.
references/не анализировалась.- В
specsприсутствуют staged additions/deletions артефактов двух изменений; это нестабильное состояние рабочей копии, а не подтверждённый стабильный релиз. - Команда
opsxотсутствует в среде, поэтому обязательная lifecycle-проверкаopsx-verifyне была выполнена.
Карта зрелости
| Область | Оценка | Основание |
|---|---|---|
| Код backend | Требует приоритетных исправлений | Сильные криптография и денежная арифметика, но есть риски ротации и отзыва сессий. |
| Код frontend | Удовлетворительно | Типизированный API и UI-состояния устойчивы; A-11/A-12 закрыты, но остаётся production fallback (A-03). |
| Тестовые сценарии | Требует усиления | Frontend покрыт (transport + UI resilience); backend concurrent E2E отсутствует. |
| Документация | Требует исправлений | Feature docs полезны, но часть устарела; architecture/development пока заглушки. |
| OpenSpec | Удовлетворительно с риском процесса | Основные спецификации качественные и валидны, но lifecycle и traceability между репозиториями недостаточны. |
| Артефакты для AI-агентов | Удовлетворительно с риском процесса | Границы репозиториев заданы хорошо, но OpenSpec context и multi-repo verification не формализованы. |
Приоритетный backlog
| Приоритет | ID | Область | Владелец | Краткое действие | Статус | Зависимости |
|---|---|---|---|---|---|---|
| High | A-01 | Безопасность сессий | backend | Сделать refresh rotation атомарной. | open | Prisma conditional update/transaction. |
| High | A-02 | Отзыв сессий | backend | Проверять активность sid либо документировать ограниченную модель отзыва access token. |
open | Решение о DB lookup/cache в guard. |
| High | A-03 | Production transport | frontend | Убрать fallback на localhost для production; использовать явный origin или same-origin /api. |
open | Контракт reverse proxy и env. |
| High | A-04 | Документация T-Bank | docs | Исправить устаревшее ограничение про счета и портфели. | open | Нет. |
| High | A-05 | OpenSpec lifecycle | specs | Атомарно завершить архивирование либо восстановить активные артефакты. | partial | Подтверждение намеренного lifecycle. |
| High | A-06 | Операционная документация | docs | Добавить архитектурную карту и workflow разработки/верификации. | partial | Подтверждение команд и границ от frontend/backend. |
| Medium | A-07 | Регистрация | backend | Преобразовать unique-constraint race в EMAIL_ALREADY_REGISTERED. |
open | Prisma error type/code. |
| Medium | A-08 | API errors | backend | Исправить сериализацию validation errors. | open | Нет. |
| Medium | A-09 | Сессии и cache | backend | Ввести retention/index для sessions и bounded TTL/LRU cache для portfolio metadata. | open | Политика retention и лимиты. |
| Medium | A-10 | Большие портфели | backend | Ограничить параллелизм получения metadata ниже лимита очереди клиента. | open | Целевой latency limit. |
| Medium | A-11 | Auth transport | frontend | Синхронизировать восстановленный token с accessTokenRef. |
done | Нет. |
| Medium | A-12 | FSD | frontend | Перевести внешние импорты слайсов на public API. | done | Нет. |
| Medium | A-13 | Тестовые сценарии | frontend/backend | Добавить конкурентные auth E2E и behavior-тесты T-Bank UI. | partial | A-01, A-07; React Query test wrapper. |
| Medium | A-14 | ADR и OpenSpec context | docs/specs/root | Актуализировать ADR, заполнить OpenSpec context и multi-repo evidence. | open | Согласование общей политики. |
Находки
High
A-01. Ротация refresh token не атомарна — [open]
- Доказательство:
backend/src/auth/auth.service.ts:75-96,148-166выполняет read/verify/update в отдельных действиях. - Обновление 2026-08-14: код не менялся; риск сохраняется.
- Риск: два параллельных запроса с одним cookie могут оба пройти проверку и получить access token; итоговый hash зависит от последней записи.
- Минимальное действие: обновлять с условием по
id,refreshTokenHash, активности и сроку жизни; считать нулевое число обновлений отказом. - Владелец: backend. Зависимости: Prisma conditional update/transaction.
A-02. Отзыв сессии не прекращает действие уже выданного access JWT — [open]
- Доказательство:
backend/src/auth/jwt.strategy.ts:19-23,backend/src/auth/jwt-auth.guard.ts:4-5,backend/src/auth/auth.service.ts:89-94,114-117проверяют подпись, срок и тип token, но не состояниеsid. - Обновление 2026-08-14: backend не менялся; риск сохраняется.
- Минимальное действие: проверять активный неистёкший
sidв guard/strategy либо явно принять и документировать bounded-revocation модель. - Владелец: backend. Зависимости: решение о lookup/cache.
A-03. Production fallback направляет bearer token на localhost пользователя — [open]
- Доказательство:
frontend/src/shared/api/config.ts:1-2используетhttp://localhost:3000при отсутствии build-time URL;frontend/src/shared/api/client.ts:54-57направляет туда bearer-authenticated requests. - Обновление 2026-08-14: fallback
?? "http://localhost:3000"перенесён вfrontend/src/shared/api/client.ts:6; риск сохраняется. - Минимальное действие: требовать явный production API origin либо использовать same-origin
/api; завершать build/start при отсутствии допустимой настройки. - Владелец: frontend. Зависимости: env и reverse-proxy contract.
A-04. Документация T-Bank противоречит реализованным функциям — [open]
- Доказательство:
docs/features/tbank-connection.md:38-40откладывает счета и портфели, ноdocs/features/brokerage-accounts.md:1-55иdocs/features/portfolio-view.md:1-59описывают их как поставленные. - Обновление 2026-08-14: не исправлено.
- Минимальное действие: оставить в limitations только реально отложенные возможности.
- Владелец: docs. Зависимости: нет.
A-05. Активные OpenSpec changes находятся в неполном переходном состоянии — [partial]
- Доказательство:
git statusвspecsпоказывает staged additions/deletionsdesign.md, delta-spec иtasks.mdдляadd-brokerage-accountsиadd-portfolio-view; правила требуют полный набор вspecs/AGENTS.md:16-17. - Обновление 2026-08-14:
align-frontend-foundationиalign-frontend-ui-patternsархивированы вarchive/и закоммичены в HEAD, но в индексе остаются 16 staged-записейAD(включая новые изменения);git statusне чист, требуетсяgit resetдля завершения lifecycle. - Минимальное действие: одним коммитом завершить archive/move либо восстановить активные артефакты.
- Владелец: specs. Зависимости: подтверждение lifecycle.
A-06. Архитектурная и development-документация фактически отсутствуют — [partial]
- Доказательство:
docs/architecture/README.md:1-3иdocs/development/README.md:1-3содержат только заглушки, хотя их назначение закреплено вdocs/AGENTS.md:15-17. - Обновление 2026-08-14: добавлена
docs/development/frontend-workflow.md(Node 22,npm run verify,openapi:sync);docs/architecture/README.mdостаётся заглушкой. - Минимальное действие: добавить актуальную component/data-flow карту и руководство по setup, generation, verification и выпуску изменений.
- Владелец: docs. Зависимости: подтверждение команд и границ frontend/backend.
Medium
A-07. Конкурентная регистрация возвращает 500 вместо контрактного 409 — [open]
- Доказательство:
backend/src/auth/auth.service.ts:29-42делает preflightfindUnique, не обрабатывая unique-constraint вокругcreate. - Риск: один из параллельных запросов с одинаковым email завершится не
EMAIL_ALREADY_REGISTERED. - Минимальное действие: перехватывать Prisma unique-constraint и возвращать
ConflictException. - Владелец: backend. Зависимости: Prisma error type/code.
A-08. Формат validation error не соответствует фактическому Nest payload — [open]
- Доказательство:
backend/src/common/filters/http-exception.filter.ts:23-38,58-66трактуетmessage: string[]какValidationError[]. - Риск: публичный
VALIDATION_ERRORсодержит пустойerrors, клиент не получает указания на неверные поля. - Минимальное действие: задать
exceptionFactoryсValidationError[]или корректно сериализовать строки Nest. - Владелец: backend. Зависимости: нет.
A-09. Сессии и portfolio cache не имеют границ роста — [open]
- Доказательство:
backend/src/auth/auth.service.ts:137-165,backend/prisma/schema.prisma:28-39не очищают sessions и не содержат expiry index;backend/src/tbank/portfolio.service.ts:54-55,67-98,229-273держит неограниченные process-local maps. - Риск: рост SQLite-таблицы и памяти при длительной эксплуатации.
- Минимальное действие: retention/cleanup сессий и index
expiresAt; bounded TTL/LRU с периодической очисткой cache. - Владелец: backend. Зависимости: политика retention, лимиты cache.
A-10. Большой портфель может терять metadata из-за burst concurrency — [open]
- Доказательство:
backend/src/tbank/portfolio.service.ts:131-133,229-272запускает все lookups одновременно,backend/src/tbank/tbank.client.ts:208-209отклоняет новые вызовы после 50 queued. - Риск: часть позиций получает fallback FIGI/
Unknown instrument, хотя данные доступны upstream. - Минимальное действие: bounded concurrency ниже лимита очереди либо очередь без hard rejection.
- Владелец: backend. Зависимости: допустимая latency для крупных портфелей.
A-11. Восстановленный access token не синхронизируется с transport ref — [done]
- Доказательство:
frontend/src/features/auth/model/auth.tsx:66-75обновляет state, но неaccessTokenRef.current;:100-110настраивает shared client только из ref. - Обновление 2026-08-14: исправлено.
auth.tsxсинхронизируетaccessTokenRef.currentпри bootstrap/refresh/login/logout/clear (строки 54,74,87,96,108); transport — единственный владелец Bearer header, покрыт тестами вclient.test.ts. - Минимальное действие: синхронно обновлять ref при восстановлении token; затем удалить дублирующиеся headers.
- Владелец: frontend. Зависимости: нет.
A-12. Нарушается FSD public API boundary — [done]
- Доказательство:
frontend/src/app/routes/AppRoutes.tsx:2-9,src/pages/accounts/ui/AccountsPage.tsx:5-10,src/pages/settings/ui/SettingsPage.tsx:4-6,src/features/tbank-connection/ui/TbankConnectionSection.tsx:13-16импортируют внутренности слайсов вопрекиfrontend/docs/STRUCTURE.md:11. - Обновление 2026-08-14: исправлено. Импорты идут через public
index.ts, добавленdependency-cruiser;npm run depsпроходит без нарушений (84 modules). - Минимальное действие: экспортировать нужные элементы через
index.tsи импортировать только public API. - Владелец: frontend. Зависимости: нет.
A-13. Критичные сценарии не защищены тестами — [partial]
- Доказательство:
backend/test/app.e2e-spec.ts:36-85не тестирует параллельные refresh/registration;frontend/src/features/tbank-connection/ui/TbankConnectionSection.tsx:27-169не имеет focused tests. - Обновление 2026-08-14: frontend-часть закрыта — transport-тесты (
client.test.ts),RouteErrorBoundary.test.tsx,AccountPage.test.tsx,TbankConnectionSection.view.test.tsx;vitest run30/30. Backend-часть (concurrent auth E2E) не добавлена — backend не менялся. - Минимальное действие: добавить concurrent E2E для auth и behavior tests для replace/delete/error/pending/invalidation UI.
- Владелец: backend и frontend. Зависимости: A-01, A-07; React Query test wrapper.
A-14. Контекст и verification evidence не адаптированы к multi-repo SDD — [open]
- Доказательство:
specs/openspec/config.yaml:1-20оставлен примером;.opencode/skills/openspec-verify-change/SKILL.md:70-115не требует evidence matrix поfrontend,backend,docs; архивные tasks, напримерspecs/openspec/changes/archive/2026-08-13-add-portfolio-view/tasks.md:13-15,23-32, не содержат commit SHA и результаты проверок. - Обновление 2026-08-14: не менялось;
config.yamlвсё ещё пример. - Минимальное действие: задать OpenSpec context/rules и completion record: репозиторий, SHA, версия/ревизия контракта, дата и результат проверок.
- Владелец: specs и root. Зависимости: соглашение frontend/backend/docs.
Low
A-15. ADR отражают план, а не реализованное состояние — [open]
- Доказательство:
docs/adr/003-tbank-server-side-grpc-boundary.md:19-21,004-encrypted-per-user-tbank-token.md:13-15,006-auth-session-policy.md:13-15описывают будущую реализацию; feature docs фиксируют поставленные функции. - Риск: читатель не отличит accepted decision от delivery status.
- Минимальное действие: дополнить consequences статусом реализации и ссылкой на feature doc; обновить конфликтующий policy в
docs/adr/007-react-query-fetch-policy.md:9-15. - Владелец: docs. Зависимости: согласование frontend/backend policy.
A-16. Локальные frontend guides не имеют явного статуса в общей документации — [open]
- Доказательство:
frontend/AGENTS.md:19-24требует читать пять внутренних документов, а корневойAGENTS.md:17,23описывает только durable docs. - Риск: агенту неясно, какая документация авторитетна и как поддерживать локальные convention guides.
- Минимальное действие: отметить их как frontend-local conventions и связать с development index.
- Владелец: root. Зависимости: согласование frontend/docs.
A-17. Небольшие UX/i18n несоответствия — [open]
- Доказательство:
frontend/src/features/auth/ui/AuthForm.tsx:84-99не содержитautoComplete;src/entities/brokerage-account/ui/BrokerageAccountList.tsx:33-38,src/entities/portfolio/model/display.ts:20-25,src/features/tbank-connection/ui/TbankConnectionSection.tsx:99-104жёстко используютru-RUпри наличии i18n. - Риск: хуже работа password manager и некорректный формат дат при добавлении другой локали.
- Минимальное действие: добавить semantic autocomplete и использовать текущий язык i18n в formatters.
- Владелец: frontend. Зависимости: решение о дополнительных локалях для второй части.
A-18. Непоследовательное оформление основной OpenSpec — [open]
- Доказательство:
specs/openspec/specs/user-authentication/spec.md:1-5начинается с## Purpose, в отличие от остальных спецификаций, напримерspecs/openspec/specs/tbank-connection/spec.md:1-7. - Риск: небольшая навигационная и tooling-неоднозначность.
- Минимальное действие: добавить
# user-authentication Specification. - Владелец: specs. Зависимости: нет.
Подтверждённые сильные стороны
- T-Bank tokens шифруются AES-256-GCM с уникальным nonce и authentication tag:
backend/src/tbank/tbank.crypto.ts:16-43. - Tokens валидируются до сохранения и не возвращаются connection status API:
backend/src/tbank/tbank-connection.service.ts:34-61,backend/src/tbank/tbank-connection.controller.ts:35-55. - JWT algorithm закреплён, а для неизвестного пользователя используется dummy bcrypt hash:
backend/src/auth/jwt.strategy.ts:11-16,backend/src/auth/auth.service.ts:50-58. - Денежная арифметика использует
bigint, не floating point:backend/src/tbank/decimal.ts:1-44. - Frontend использует централизованный типизированный OpenAPI client, не хранит token в persistent storage, а маршруты и страницы имеют loading/error/empty patterns.
- Основные OpenSpec scenario-based, охватывают ошибки, cache и безопасность; feature docs содержат пользовательские потоки, API, ограничения и Mermaid diagrams.
- Корневые и локальные
AGENTS.mdясно фиксируют независимые репозитории и SDD intent.
Результаты воспроизводимых проверок
Проверки выполнены 2026-08-13 без запуска test:cov и без анализа процентов покрытия. Повторные проверки frontend — 2026-08-14.
| Область | Команда | Результат |
|---|---|---|
| frontend | ./node_modules/.bin/biome check . |
Успешно: 64 файла, замечаний нет. |
| frontend | ./node_modules/.bin/tsc -b --noEmit |
Успешно. |
| frontend | ./node_modules/.bin/vitest run |
Успешно: 8 files, 25 tests. |
| frontend | ./node_modules/.bin/tsc -b && ./node_modules/.bin/vite build |
Успешно; Vite предупреждает о JS chunk 582.99 kB (176.19 kB gzip) после minification. |
| frontend | ! rg -i todo src --glob '*.{ts,tsx}' |
Успешно: TODO не найдено. |
| backend | rtk lint "{src,apps,libs,test}/**/*.ts" |
Успешно: ESLint без замечаний. |
| backend | npm test |
Успешно: 8 suites, 22 tests. |
| backend | rtk npm run build |
Успешно: Prisma generate и Nest build. |
| specs | npx openspec validate --all --strict |
Успешно: 7 specs, 0 failures. |
| specs | opsx validate --all --strict |
Не выполнено: opsx: command not found. |
Повторные проверки 2026-08-14
| Область | Команда | Результат |
|---|---|---|
| frontend | npm run typecheck |
Успешно. |
| frontend | ./node_modules/.bin/biome check . |
Успешно: 81 файл, замечаний нет. |
| frontend | npm run openapi:check |
Успешно: generated artifact соответствует committed snapshot. |
| frontend | npm run deps |
Успешно: dependency-cruiser, 84 modules, нарушений нет. |
| frontend | npm run knip |
Успешно. |
| frontend | vitest run |
Успешно: 30 tests (11 files). |
| specs | npx openspec validate --all --strict |
Успешно: 8 specs (добавлен frontend-ui-resilience), 0 failures. |
| specs | git status |
Грязный: 16 staged-записей AD в openspec/changes/ — ожидает git reset. |
Рекомендуемый порядок исправлений
- Создать одну security-focused change для A-01, A-02, A-03 и A-07; добавить связанные concurrent tests из A-13 (backend-часть). Это единственный незакрытый High-блок.
- Завершить lifecycle A-05: выполнить
git resetвspecs, чтобы убрать 16 staged-записейADи вернуть воспроизводимый OpenSpec store. - Исправить A-04, A-06, A-14 и A-15 одним documentation/process change, включив multi-repo evidence matrix.
- Выполнить A-08, A-09 и A-10 отдельными backend-изменениями.
- Завершить Low-улучшения (A-16, A-17, A-18) после согласования локалей и статуса локальных руководств.