54 KiB
Реализация ручного учёта банковских карт
Статус: согласованный объём реализован и проверен 12 сентября 2026 года. Независимое ревью завершено; change остаётся активным, без архивирования и синхронизации в основные specs. Основание — согласованные Design revision 1, включая полностью inline UI/UX package revision 1, и Delta Specs. Внешних визуальных материалов или дополнительных пакетов для начала нет.
Checkbox закрывается только после выполнения действия и его Verification.
Verification ниже задаёт критерии; наблюдённые результаты отмечаются отдельно.
Перед Node-командами из affected repo выполняются
source ~/.nvm/nvm.sh && nvm use --silent; для specs используется frontend
.nvmrc. Git-команды выполняются из соответствующего независимого репозитория.
DB/HTTP-проверки используют уникальную временную SQLite с вымышленными данными
и явно заданной DATABASE_URL, без доступа к пользовательской базе или T-Bank.
Общий npm run test:e2e с фиксированной /tmp/wealth-ledger-e2e.db для них
не используется. Рабочая финансовая база не сбрасывается и не заменяется
ради выполнения проверки.
Задачи одного раздела выполняются по указанным зависимостям. Задача 1.2 может идти независимо от 1.1; остальные параллельные работы допустимы только при закрытых зависимостях и раздельном владении изменяемыми файлами.
1. Основа хранения и точных денег
-
1.1 [backend] Подтвердить применимость выбранного Solution Assessment: существующие Prisma/SQLite и migration boundary под Node 22; зафиксировать исходную версию схемы/приложения для проверки перехода и отката.
- Covers:
N/A— техническое предусловие нового долговременного хранения из Design, без самостоятельного пользовательского поведения или смены выбранной архитектуры. - Verification:
npx prisma validate; существующие migrations применяются черезnpx prisma migrate deployсDATABASE_URLкаждой уникальной временной базы. Для снятия известного blocker нужны три последовательных успешных fresh-DB применения согласно правилу проверки. При ошибке сохранить версию и точный failure, не закрывать задачу и не подменять migration proof черезdb push, reset или ручной обход migrations. - Результат 2026-09-12: Node
22.21.0, Prisma/client7.9.1, enginee922089b7d7502aff4249d5da3420f6fa55fc6ad;prisma validate— passed. Исходный backend8ec172f48eefa2237dc0c16919fbb2e726b39a65, frontend427ca23a433a20be25b1f4373f32c9e1f6f8c400; оба working tree были чистыми. Обычный fresh deploy воспроизвёлError: Schema engine error:без деталей, в том числе вне sandbox. СRUST_LOG=infoштатныйnpx prisma migrate deployвне sandbox прошёл три раза подряд:/tmp/wealthledger-bank-cards-migrations-logging.rFEHKw/fresh-{1,2,3}.db, логиmigrate-{1,2,3}.logрядом. В каждом применены обе исходные migrations. Это подтверждает путь с указанной переменной окружения; запуск без неё остаётся ограничением. Версии зависимостей, применённые migrations и пользовательская база не менялись.
- Covers:
-
1.2 [backend] Выделить общего владельца decimal parsing/formatting и MoneyDto, сохранить protobuf-преобразование у T-Bank и добавить точное преобразование допустимого RUB-ввода в копейки.
- Covers:
manual-bank-cards—Точные денежные значения и проверка до сохранения. - Verification: существующие decimal и затронутые брокерские calculation tests проходят до и после переноса; targeted Jest проверяет signed-64-bit границы, отрицательный/нулевой начальный остаток, строго положительную сумму операции, запрет лишней точности и точный Money roundtrip.
npm run typecheck:app; прежний Money wire contract сохраняется. - Результат 2026-09-12: общий owner
src/common/decimal.ts,money.dto.ts,rub-money.ts; protobuf-преобразование осталось в T-Bank. До переносаnpm test -- --runInBand src/tbank— 24 suites / 191 tests passed; послеnpm test -- --runInBand 'src/tbank|src/common/rub-money'— 25 suites / 213 tests passed. Targeted ESLint,npm run typecheck:app,git diff --check— passed.npm run test:openapi-contractдо добавления банковских endpoints подтвердил неизменность прежнего контракта, но проверка обнаружила безусловную замену внешнегоDATABASE_URLвtest/e2e-env.cjsна фиксированную временную базу. Этот запуск не принимается как доказательство требуемой изоляции; после исправления test setup сравнение повторяется на уникальной базе. Пользовательская база не использовалась. Новый banking API требует отдельного финального сравнения.
- Covers:
-
1.3 [backend] После 1.1 добавить BankCard, ExpenseCategory и BankCardOperation, additive migration, связи, ограничения уникальности, индексы, версии, tombstones и fingerprints из Design.
- Covers:
manual-bank-cards—Сохранённый ручной учёт переживает повторный вход и перезапуск;manual-bank-cards—Точные денежные значения и проверка до сохранения. - Verification:
npx prisma validate,npx prisma generate,npm run typecheck:app; migration на изолированной базе с representative User/Session/TbankConnection сохраняет их данные. Реальная DB-проверка подтверждает FK/unique constraints и точное хранение копеек больше2^53и обеих граничных величин; применённые migrations не переписаны.
- Covers:
Если для устранения подтверждённого migration blocker потребуется другой подход или изменение согласованного стека, это возвращает решение в Design. Успех unit/Swagger-проверки не разрешает закрыть 1.1 или 1.3 без DB-доказательства.
Результат 1.3: additive migration 20260912090000_add_manual_bank_cards
(существующие migrations неизменны), prisma validate/generate и app typecheck
— passed. Реальный adapter/Prisma roundtrip подтвердил 9007199254740993n
и обе signed64 границы; configured DB-тесты подтвердили FK/unique.
Переход с исходной схемы сохранил representative User/Session/TbankConnection
в проверке сохранности 3.4.
2. Backend: пользовательский учёт и денежные изменения
-
2.1 [backend] После 1.2–1.3 создать BankCardsModule и сервис сценариев: добавление карт с защитой повторов, пользовательские категории, начальный набор и переименование с сохранением идентичности и default role.
- Covers:
manual-bank-cards—Ручное добавление независимых банковских карт;manual-bank-cards—Общие для пользователя категории расходов;manual-bank-cards—Изоляция пользовательских финансовых данных;manual-bank-cards—Согласованные изменения и защита повторной отправки. - Verification: targeted service/DB cases проверяют ограничения сведений карты, собственника, atomic card+seed creation, concurrent first-card creation без дублей категорий, регистронезависимую уникальность, rename default category и same-intent create карты с тем же/другим содержанием. Чтение не создаёт данных и не обращается к T-Bank.
- Covers:
-
2.2 [backend] После 1.2 реализовать чистые правила календарных дат и точные расчёты баланса и месячных расходов из первичных записей, сохранив O(N) подход Design.
- Covers:
manual-bank-cards—Даты начала учёта и ручных операций;manual-bank-cards—Баланс определяется начальным остатком и внесёнными операциями;manual-bank-cards—Месячный журнал и сводка расходов по категориям. - Verification: targeted Jest проверяет
1 − 0,10 − 0,20 = 0,70, отрицательный баланс, итог выше предела отдельного ввода, московскую границу дня/месяца, реальные календарные даты, возврат прошлого месяца и исключение переводов/пополнений из расходов. Расчёт не зависит от страницы журнала; комментарийponytail:фиксирует предел O(N) и условие оптимизации.
- Covers:
-
2.3 [backend] После 2.1–2.2 реализовать создание расходов и пополнений с проверкой карты/категории/дат, транзакцией и разрешением сохранённого намерения до повторной проверки изменяемых условий.
- Covers:
manual-bank-cards—Ручное внесение расходов и пополнений;manual-bank-cards—Согласованные изменения и защита повторной отправки;manual-bank-cards—Изоляция пользовательских финансовых данных. - Verification: service/DB cases проверяют default category, сохранение при отрицательном остатке, отказ чужим ссылкам и недопустимому вводу без частичной записи; same UUID не создаёт дубликат, другой payload даёт конфликт, две независимые успешные траты сохраняются обе.
- Covers:
-
2.4 [backend] После 2.3 реализовать перевод одной записью с проверкой обеих карт и дат начала учёта, двумя проекциями истории и общим денежным эффектом.
- Covers:
manual-bank-cards—Перевод между своими картами как одно действие;manual-bank-cards—Даты начала учёта и ручных операций;manual-bank-cards—Изоляция пользовательских финансовых данных. - Verification: реальная DB-проверка подтверждает обе стороны перевода, допустимый отрицательный остаток источника и отсутствие частичного результата при ошибке; отклоняются одинаковые, чужие и архивные карты и дата до начала учёта любой стороны. Сумма не включается в расходы одной или всех карт.
- Covers:
-
2.5 [backend] После 2.3 реализовать связанные частичные и повторные возвраты, наследование категории покупки, общий лимит и чтение доступных исходных расходов за любой период.
- Covers:
manual-bank-cards—Возврат связан с исходным расходом;manual-bank-cards—Согласованные изменения и защита повторной отправки;manual-bank-cards—Изоляция пользовательских финансовых данных. - Verification: DB cases проверяют несколько возвратов, исходный расход прошлого месяца, чужую/удалённую покупку, дату до покупки и два конкурирующих возврата с превышением общего лимита. Повтор успешно сохранённого полного возврата после потерянного ответа возвращает существующий результат без ошибки нового лимита и без дубликата.
- Covers:
-
2.6 [backend] После 2.4–2.5 реализовать version-protected исправление и логическое удаление всех видов операций с проверкой прежних и новых связей, сохранением creation fingerprint и запретом изменения вида/исходной покупки возврата.
- Covers:
manual-bank-cards—Исправление и удаление операций с согласованным пересчётом;manual-bank-cards—Возврат связан с исходным расходом;manual-bank-cards—Согласованные изменения и защита повторной отправки. - Verification: DB cases покрывают перенос расхода/пополнения между картами, смену получателя и удаление целого перевода, смену месяца/категории, ограничения исходного расхода с возвратами, edit refund с исключением собственной прежней суммы, stale edit/delete и повтор delete. Late create retry после edit/delete не возвращает старые суммы и не воскрешает запись; гонка refund с уменьшением покупки сохраняет общий лимит.
- Covers:
-
2.7 [backend] После 2.6 реализовать изменение сведений и начала учёта карты, архив и возврат из архива с проверкой всей затронутой истории и version conflict.
- Covers:
manual-bank-cards—Ручное добавление независимых банковских карт;manual-bank-cards—Исправление начала ручного учёта;manual-bank-cards—Архив карт сохраняет историю;manual-bank-cards—Согласованные изменения и защита повторной отправки. - Verification: DB cases проверяют opening balance без новой операции/изменения месячных трат, недопустимое новое начало с входящим переводом, архив при любом остатке, запрет create/edit/delete по архиву, unarchive и stale card edit. Гонка архива или смены даты с финансовым изменением даёт последовательный допустимый результат; повтор create архивированной карты возвращает ту же архивную карту.
- Covers:
Результат раздела 2: src/bank-cards/bank-card.calculations.spec.ts — 23
pure tests passed; полный backend gate — 33 suites / 253 tests passed.
test/bank-cards.e2e-spec.ts — 18 configured HTTP/SQLite tests passed
(/tmp/bank-cards-http.log): атомарные повторы/переводы, независимые траты,
конкурирующие возвраты и уменьшение покупки, смена начала/архив одновременно
с операцией, версии, foreign ownership, исправления/удаления, категории и
точные денежные границы. Fixtures вымышленные, URL уникальный; setup сохраняет
внешний DATABASE_URL, банковский suite запрещает shared/user DB.
3. Backend: чтение, HTTP и доказательство сохранности
-
3.1 [backend] После раздела 2 подключить расчёты к согласованным чтениям списка/деталей карт, месячного журнала, исходных расходов возврата и сводок одной/всех карт.
- Covers:
manual-bank-cards—Баланс определяется начальным остатком и внесёнными операциями;manual-bank-cards—Месячный журнал и сводка расходов по категориям;manual-bank-cards—Архив карт сохраняет историю;manual-bank-cards—Возврат связан с исходным расходом. - Verification: integration cases проверяют пагинацию и стабильный порядок равных дат, весь набор для баланса/сводки, отрицательный net, архив в общей сводке, перенос между месяцами и перегруппировку связанных возвратов после изменения категории покупки. Связанные данные одного ответа согласованы; отсутствуют server cache и materialized balance.
- Covers:
-
3.2 [backend] После 3.1 завершить controller/runtime DTO под
/api/v1/bank-cards, подключить существующие JWT/filter и сформировать полный runtime OpenAPI для frontend.- Covers:
manual-bank-cards—Отдельный раздел ручного учёта банковских карт;manual-bank-cards—Точные денежные значения и проверка до сохранения;manual-bank-cards—Даты начала учёта и ручных операций;manual-bank-cards—Изоляция пользовательских финансовых данных. - Verification: configured HTTP cases проверяют фактические validation/status/error codes, отсутствие сессии, чужие связи, архив/version/refund conflicts, безопасность ответов и работу без T-Bank. Runtime OpenAPI отражает действующие DTO и Money; сырые Prisma records не выдаются вместо оговорённого контракта, финансовые DTO не попадают в ответы с ошибками.
- Covers:
-
3.3 [backend] После 3.2 завершить runnable configured HTTP/DB проверки критических сценариев и конкурентных изменений в отдельной временной базе, дополнив уже созданные cases вместо их дублирования.
- Covers:
manual-bank-cards—Согласованные изменения и защита повторной отправки;manual-bank-cards—Изоляция пользовательских финансовых данных;manual-bank-cards—Исправление и удаление операций с согласованным пересчётом;manual-bank-cards—Доступные формы и различимые состояния без ложного успеха. - Verification: с уникальной
DATABASE_URLвыполнитьNODE_ENV=development NODE_OPTIONS=--experimental-vm-modules npx jest --config ./test/jest-e2e.json --runInBand bank-cards. Проверяемые исходы: один результат concurrent same-intent create карты/операции, сохранность обеих независимых трат, no partial transfer/refund, stale conflicts, архивные/чужие ссылки, loss-of-response replay и отсутствие ложного успеха. Mock Prisma не заменяет DB cases.
- Covers:
-
3.4 [backend] После 3.3 доказать долговременность ручных данных, корректный backup/restore и совместимость отката приложения с расширенной схемой без удаления новой истории.
- Covers:
manual-bank-cards—Сохранённый ручной учёт переживает повторный вход и перезапуск;manual-bank-cards—Согласованные изменения и защита повторной отправки. - Verification: на disposable базах перезапуск сохраняет карты, операции, связи, переименованные категории, архив, tombstones и fingerprints; повтор после перезапуска не создаёт дубликат. Проверяются согласованный SQLite backup/restore, сохранность User/Session/TbankConnection, запуск исходной версии приложения с additive schema и доступность новых записей после возврата новой версии. Старый backup не восстанавливается поверх новой истории как штатный rollback.
- Covers:
Результат раздела 3: те же 18 HTTP/DB tests подтверждают чтения, пагинацию,
month/category regrouping, validation/status и безопасные ошибки без T-Bank.
Дополнительный процессный сценарий node /tmp/bank-cards-durability.cjs — passed:
исходный backend собран из Git archive 8ec172f48eefa2237dc0c16919fbb2e726b39a65
в /tmp/wealthledger-bank-baseline.8hcDz3; миграция сохранила старые таблицы,
перезапуск — категории/архив/возвраты/tombstones/fingerprints, старое приложение
запустилось с расширенной схемой, новое вновь прочитало историю, согласованный
SQLite backup восстановлен и прочитан приложением. Свидетельство:
/var/folders/j_/h2ft23gd3qq35ps3v5bcftfm0000gn/T/wealthledger-bank-durability-hPvsEO/result.json.
Runnable версия сохранена в backend/test/bank-cards-durability.cjs; ей
передаётся каталог отдельно собранной исходной версии. Проверки создают свои
временные базы; старый backup не записывается поверх новой истории.
4. Контракт и слой данных frontend
-
4.1 [frontend] После 3.2 обновить committed OpenAPI snapshot из настроенного backend runtime document и сгенерировать frontend types, сохранив backend единственным editable HTTP source.
- Covers:
N/A— производные артефакты двустороннего контракта из Design обеспечивают типизированного потребителя, но не вводят отдельного пользовательского поведения. - Verification:
npm run openapi:generate,npm run openapi:check,npm run typecheck; snapshot получен по существующему workflow, generated types не исправлялись вручную, существующие инвестиционные Money-контракты сохранены.
- Covers:
-
4.2 [frontend] После 4.1 добавить banking queries/mutations у domain owner: session-aware transport, стабильный create UUID, version inputs, безопасные retries и invalidation всех затронутых банковских GET-представлений.
- Covers:
manual-bank-cards—Согласованные изменения и защита повторной отправки;manual-bank-cards—Изоляция пользовательских финансовых данных;manual-bank-cards—Отдельный раздел ручного учёта банковских карт;manual-bank-cards—Доступные формы и различимые состояния без ложного успеха. - Verification: Vitest/MSW через
npm run test:run -- src/entities/bank-cardпроверяют одинаковый UUID при network/auth retry, отсутствие optimistic balance, invalidation обеих карт/всех месяцев/исходных расходов, rename категории, сохранение данных при ошибке, GET после version conflict, logout isolation и независимость от T-Bank connection mutation. Свой refresh loop и второй query cache отсутствуют.
- Covers:
Результат 4.2: src/entities/bank-card/api/banking.test.tsx — 10 MSW tests
passed; typecheck, focused Biome и dependency boundaries — passed. Повторы
сохраняют UUID, подтверждённые mutations инвалидируют только все banking GETs,
конфликты вызывают перечитывание, ошибки не меняют суммы оптимистически.
Дополнены реальные feature tests AuthProvider/TbankConnectionSection: 10 tests
passed доказывают очистку banking cache при logout/refresh failure и его
сохранение без invalidation при connect/replace/delete T-Bank.
Результат 4.1: snapshot экспортирован из configured runtime Nest/Swagger
(42 paths) на уникальной временной SQLite, включая банковские 409/410.
npm run openapi:generate, npm run openapi:check, npm run typecheck — passed;
generated types не редактировались вручную. После финального добавления
описаний 409/410 snapshot/types повторно сгенерированы, openapi:check passed.
5. Экраны и формы из UI/UX package revision 1
Все задачи раздела используют существующие Mantine-тему, i18n, container/VM/view, RHF/Zod и shared UI из Design. Проверки формы и состояний выполняются через видимый результат и сеть MSW; отдельный тест декларативной обёртки не нужен.
-
5.1 [frontend] После 4.2 собрать
/cards: навигацию, список активных карт и архива, месячную сводку всех карт и форму добавления карты с начальным остатком/датой.- Covers:
manual-bank-cards—Отдельный раздел ручного учёта банковских карт;manual-bank-cards—Ручное добавление независимых банковских карт;manual-bank-cards—Месячный журнал и сводка расходов по категориям;manual-bank-cards—Доступные формы и различимые состояния без ложного успеха. - Verification:
npm run test:run -- src/pages/cardsи targeted route tests проверяют login/returnTo без T-Bank, обязательные/необязательные поля, точный отрицательный остаток, no request при invalid, блокировку pending, сохранение ввода при ошибке и один create UUID при повторе. Loaded/empty/error/skeleton и архивный переключатель соответствуют Design; сводка всех карт включает архив независимо от фильтра списка.
- Covers:
-
5.2 [frontend] После 5.1 собрать
/cards/:id: крошки и title, текущий баланс, общий выбор месяца для журнала/сводки, пагинацию и представления четырёх видов операций.- Covers:
manual-bank-cards—Баланс определяется начальным остатком и внесёнными операциями;manual-bank-cards—Месячный журнал и сводка расходов по категориям;manual-bank-cards—Архив карт сохраняет историю;manual-bank-cards—Доступные формы и различимые состояния без ложного успеха. - Verification:
npm run test:run -- src/pages/cardпроверяет month/URL и страницу, неизменный текущий баланс, расходы/возвраты/net со знаком, понятные стороны перевода, локальную ошибку сводки, cached snapshot при refetch failure и безопасное состояние отсутствующей карты. Frontend форматирует Money без собственной финансовой арифметики.
- Covers:
-
5.3 [frontend] После 5.2 добавить формы создания расхода, пополнения и перевода с общими проверками денежного ввода/дат и сохранением одного намерения до определённого результата.
- Covers:
manual-bank-cards—Ручное внесение расходов и пополнений;manual-bank-cards—Перевод между своими картами как одно действие;manual-bank-cards—Точные денежные значения и проверка до сохранения;manual-bank-cards—Даты начала учёта и ручных операций;manual-bank-cards—Доступные формы и различимые состояния без ложного успеха. - Verification: RTL/MSW cases проверяют default category, положительную сумму/копейки без потери больших значений, даты обеих карт перевода, отрицательный итог без запрета реальной траты, visible labels, pending/ошибки с сохранённым вводом и повтор одного перевода без дубликата. Новое подтверждённое состояние приходит из банковских queries.
- Covers:
-
5.4 [frontend] После 5.3 добавить создание и редактирование возврата с выбором исходной покупки за всю историю карты и корректным лимитом текущей записи.
- Covers:
manual-bank-cards—Возврат связан с исходным расходом;manual-bank-cards—Исправление и удаление операций с согласованным пересчётом;manual-bank-cards—Месячный журнал и сводка расходов по категориям;manual-bank-cards—Согласованные изменения и защита повторной отправки. - Verification: RTL/MSW journey выбирает покупку прошлого месяца, записывает частичный возврат и видит его в месяце получения; полный возврат позволяет исправить описание, исключая собственную старую сумму из лимита. Проверяются превышение, stale source, immutable purchase link, архив, network retry полного возврата и сохранение формы без ложного успеха.
- Covers:
-
5.5 [frontend] После 5.3–5.4 добавить остальные исправления/удаления операций, изменение сведений и начала учёта карты, архив и возврат из архива с понятными конфликтами.
- Covers:
manual-bank-cards—Исправление и удаление операций с согласованным пересчётом;manual-bank-cards—Исправление начала ручного учёта;manual-bank-cards—Архив карт сохраняет историю;manual-bank-cards—Доступные формы и различимые состояния без ложного успеха. - Verification: RTL/MSW проверяет edit с version и последующим GET при конфликте, сохранение черновика, перенос между картами/месяцами, подтверждение удаления перевода с обеими картами, запреты связанного расхода и архива, opening date error и обратимый архив. После успешного действия все затронутые видимые суммы соответствуют новым серверным данным.
- Covers:
-
5.6 [frontend] После 5.3 добавить управление начальными и своими категориями и создание категории из формы расхода без потери введённой операции.
- Covers:
manual-bank-cards—Общие для пользователя категории расходов;manual-bank-cards—Ручное внесение расходов и пополнений;manual-bank-cards—Доступные формы и различимые состояния без ложного успеха. - Verification: RTL/MSW проверяет add/rename, уникальность без регистра и длину, переименование default category без утраты роли, обновление названий в истории/сводке и неизменный черновик расхода при добавлении категории. Удаление и вложенные подкатегории отсутствуют согласно scope.
- Covers:
Результат 5.1–5.6: реализованы страницы, четыре вида операций, исправления, удаление, архив и категории. RTL/MSW покрывают точный ввод и UUID после ошибки, month/page/returnTo, неизменный текущий баланс, полный возврат с собственным лимитом, stale version с явным принятием новой версии, opening-date conflict, архив, обе стороны удаления перевода и вложенное создание категории. Финальный frontend gate включает 43 test files / 263 passed tests.
Браузер обнаружил потерю нового имени категории после reset неконтролируемого поля: поле переведено на RHF Controller, исправление проверено RTL и настоящим PATCH/GET. Независимое ревью обнаружило скрытые ошибки вспомогательных GET карт/категорий: добавлены локальные сообщения и retry, две regression-проверки и browser recovery passed. Существующие authentication/инвестиционные tests прошли; returnTo сохраняет карточку и query выбранного месяца.
6. Проверка пользовательского результата и документация
-
6.1 [frontend] После 3.3–3.4 и разделов 4–5 проверить UI package в браузере с изолированным backend и подготовить Storybook-примеры новых собственных представлений на вымышленных данных.
- Covers:
manual-bank-cards—Доступные формы и различимые состояния без ложного успеха;manual-bank-cards—Отдельный раздел ручного учёта банковских карт;manual-bank-cards—Сохранённый ручной учёт переживает повторный вход и перезапуск. - Verification: реальный UI journey без T-Bank: две карты → расход/пополнение → перевод → возврат прошлой покупки → исправление/удаление → архив/unarchive → reload/login. Проверить широкий экран и 320–375 px, пять пунктов навигации, длинные суммы/названия, keyboard/focus return, reduced motion и loading/empty/error/refetch recovery. Сохранить краткие результаты и локальные визуальные свидетельства; Storybook build не подменяет браузерную проверку.
- Covers:
-
6.2 [docs] После подтверждения реализованного поведения обновить документацию: область банковских карт, глоссарий, обзор продукта и тематическую навигацию, хранимые данные, денежные правила и безопасное восстановление.
- Covers:
N/A— as-built объяснение поставленного поведения и восстановления из Delivery Map; новая норма не вводится и не копируется параллельно Delta Specs. - Verification: пройти путь README → банковские карты → понятия/расчёты/исправления и восстановление; сверить текст с поставленными flows и ограничениями, включая ручной источник баланса, отрицательные итоги, архив, повторы и сохранение новой истории при rollback. Ссылки ведут на существующие targets; исторические материалы не переписываются, обещания неподтверждённой миграции не добавляются.
- Covers:
Результат 6.1: реальный браузер работал с отдельным BrowserContext и backend на уникальной временной SQLite, с вымышленным пользователем без T-Bank. Через UI выполнены две карты (1 000 ₽ и 0 ₽), августовский расход 100 ₽, сентябрьские пополнение 200 ₽, перевод 150 ₽ и возврат 60 ₽: баланс A 1 010 ₽, B 150 ₽, сентябрьский net −60 ₽. Возврат исправлен до полного 100 ₽, его описание изменено, затем сумма возвращена к 60 ₽. Исправление покупки 100 → 150 ₽ дало A 960 ₽; удаление перевода с подтверждением обеих карт — A 1 110 ₽ и B 0 ₽. Архив сохранил историю и общий net; unarchive вернул действия.
Добавление категории из расхода сохранило сумму 12,34 ₽ и описание черновика; переименование «Другое» сохранило default role. Проверены Escape и возврат фокуса к действию, visible labels, initial loading/empty, ошибки GET и retry, сохранённый net при неудачном refetch, reduced motion. Logout → protected URL → login вернул ту же карту и август; reload сохранил баланс 1 110 ₽ и расход 150 ₽. Экран 1440 px и 320/375 px проверен визуально: пять пунктов навигации, длинное название и точная предельная сумма доступны без горизонтального overflow.
Локальные screenshots итогового UI:
/tmp/wealthledger-bank-cards-final-desktop.png,
/tmp/wealthledger-bank-cards-final-mobile.png,
/tmp/wealthledger-bank-cards-final-mobile-long.png,
/tmp/wealthledger-bank-card-final-mobile.png;
состояние cached error — /tmp/wealthledger-bank-cards-cached-error.png.
Добавлены две изолированные story groups и 9 примеров на вымышленных данных;
storybook dependency isolation и build passed.
Результат 6.2: обновлены README/overview, glossary, область cards, описание хранения, локальная миграция/восстановление и UI-каталог. Маршруты README → cards → Money/восстановление проверены; объяснения сверены с Delta Specs, реализацией и наблюдёнными flows. Новых Mermaid-диаграмм и изменений исторических ADR нет.
7. Финальные gates и состояние SDD-артефактов
Backend npm run verify — passed (/tmp/bank-cards-verify.log): lint без
warnings, app/test TypeScript, 33 suites / 253 tests, Prisma generate и build.
Последующий итоговый HTTP-прогон и independent review описаны ниже;
успех gates не является заменой semantic review.
После независимого review исправлен P2 в DTO: явный null для Money,
архива и non-null полей отклоняется; nullable реквизиты очищаются по-прежнему.
Configured HTTP/SQLite — 19/19 passed, включая 400 без изменения данных/версий;
OpenAPI parity на уникальной базе — passed, wire shape не изменился.
Итоговый npm run verify повторно passed
(/tmp/bank-cards-final-backend-verify.log). Сохранённый runnable durability
сценарий повторно passed на итоговом backend:
/var/folders/j_/h2ft23gd3qq35ps3v5bcftfm0000gn/T/wealthledger-bank-durability-dXSTmz/result.json.
Reviewer перепроверил исправление и не нашёл других backend findings.
Gate применяется к итоговому состоянию соответствующего repo. Уже прошедшие проверки не повторяются без новых изменений, сбоев или оставшегося риска. Если финальная правка меняет проверенную границу, повторяется её нужный gate.
-
7.1 [backend] После разделов 1–3 выполнить canonical backend gate и сохранить результаты DB/HTTP/durability проверок для того же состояния кода.
- Covers:
N/A— обязательная проверка backend delivery из Design, дополняющая уже покрытые поведенческие и DB cases без новой возможности. - Verification:
npm run verify; отдельные результаты 3.3–3.4 остаются применимы к итоговому коду. Type/lint/unit/build не объявляются доказательством транзакций или миграции, если DB-проверка не запускалась успешно.
- Covers:
-
7.2 [frontend] После 6.1 выполнить canonical frontend gate для итоговых API types, UI, i18n, stories и dependency boundaries.
- Covers:
N/A— обязательный frontend delivery gate из Design, без добавления самостоятельного пользовательского поведения. - Verification:
npm run verifyвключает OpenAPI drift, typecheck, lint, coverage, Knip, dependency boundaries и обе сборки. Отдельный результат браузерной проверки 6.1 сохраняет применимость; процент покрытия и Storybook build не заменяют его.
- Covers:
-
7.3 [workspace] После 4.1, 7.1 и 7.2 подтвердить двусторонний runtime OpenAPI contract по итоговому backend и frontend snapshot/types.
- Covers:
N/A— межрепозиторная verification из Contract Gate Decision, без владения кодом приложений или отдельным поведением. - Verification: из backend выполнить
npm run test:openapi-contract; использовать актуальный frontendopenapi:checkиз 7.2, не повторяя его при неизменном snapshot/types. Проверка не требует T-Bank и не изменяет snapshot автоматически.
- Covers:
-
7.4 [docs] После 6.2 выполнить canonical docs gate, ручную смысловую сверку и проверку затронутых маршрутов чтения.
- Covers:
N/A— проверка связности as-built документации из Delivery Map, без самостоятельного нормативного поведения. - Verification: из docs выполнить
npm run verify; проверить новые Markdown-файлы и затронутые внешние относительно docs ссылки. Если изменены Mermaid-диаграммы, отдельно проверить доступным локальным renderer их вид либо явно сохранить ограничение; новый стек для этого не устанавливать.
- Covers:
-
7.5 [specs] После всех implementation-owned задач сверить поставленный результат со всеми Delta Requirements и обновить этот Tasks только по выполненным действиям и наблюдённым проверкам, затем выполнить canonical validation.
- Covers:
N/A— поддержание существующих SDD-артефактов и traceability реализации из Delivery Map; новые требования, архитектура и отдельный журнал доказательств не создаются. - Verification: каждое требование
manual-bank-cardsсвязано с выполненной задачей и подходящим доказательством; все оставшиеся ограничения названы. Выполнитьopenspec validate add-manual-bank-cards --type change --strict --store wealth-ledger-specs,openspec validate --specs --strict --store wealth-ledger-specsиgit diff --check, отдельно просмотрев новые файлы и ссылки. Approval и завершение реализации не выводятся только из наличия файлов.
- Covers:
Независимая проверка результата и завершение lifecycle выполняются после implementation-owned задач; они не маскируются checkbox, который исполнитель не может закрыть сам. Этот план не включает преждевременную синхронизацию нового capability в основные specs, архивирование или изменение истории. Такие действия относятся к последующему завершению выбранного SDD lifecycle.
Итоговые результаты 7.2–7.4: frontend npm run verify — passed
(/tmp/bank-cards-final-frontend-verify.log): OpenAPI drift, TypeScript,
Biome, 43 files / 263 tests с coverage, Knip, обе dependency проверки,
app и Storybook builds. Backend npm run test:openapi-contract — passed
на уникальной базе (/tmp/bank-cards-contract.log); последний DTO fix
не меняет wire shape, frontend snapshot/types после этого не изменялись.
Docs npm run verify — passed, 54 Markdown-файла, 0 issues.
Независимое ревью backend/frontend/docs завершено: найденные null-validation,
category-form и auxiliary-query recovery дефекты исправлены и перепроверены;
открытых actionable findings нет. Обычный Prisma fresh migrate deploy без
RUST_LOG=info по-прежнему имеет указанное в 1.1 ограничение; причина
не установлена. Подтверждён только штатный путь с переменной окружения.
Предупреждение Storybook/Vite о размере chunks не препятствует сборке.
Результат 7.5: все 17 Delta Requirements сверены с реализацией и Covers/проверками
выше; 29 implementation-owned задач завершены. openspec validate add-manual-bank-cards --type change --strict --store wealth-ledger-specs — valid;
openspec validate --specs --strict --store wealth-ledger-specs — 25 passed,
0 failed. Итоговый routing повторён по modified/untracked файлам четырёх repo;
новые файлы и ссылки просмотрены, git diff --check — passed в каждом repo.
Proposal, Delta Specs, Design, основные specs и архивы не изменялись.
Последующие проверки перед commit: по запросу пользователя все четыре нативных
поля дат/месяца заменены на Mantine DateInput/MonthPickerInput. Сохранение
календарных дат, month/URL и календарь на 320 px проверены в браузере
на новой временной базе; будущие даты недоступны. Полный frontend
npm run verify повторно passed: 43 files / 263 tests и обе сборки
(/tmp/bank-mantine-verify.log).
После отдельного разрешения пользователя миграция применена к рабочей SQLite
через RUST_LOG=info npx prisma migrate deploy. До применения создан
согласованный SQLite backup; после — проверены integrity/FK и неизменность
User/Session/TbankConnection. Это обновление рабочей среды, не тестовые записи
в пользовательской базе. Backup исключён из Git; ограничение обычного запуска
Prisma без RUST_LOG=info остаётся прежним.