Files
specs/openspec/changes/archive/2026-10-09-add-manual-bank-cards/tasks.md
T
ksv741 329d66e767
Specs security / security (push) Successful in 8s
Specs verify / verify (push) Successful in 11s
spec: finalize wealth-ledger SDD migration
2026-10-09 21:14:22 +03:00

54 KiB
Raw Blame History

Реализация ручного учёта банковских карт

Статус: согласованный объём реализован и проверен 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/client 7.9.1, engine e922089b7d7502aff4249d5da3420f6fa55fc6ad; prisma validate — passed. Исходный backend 8ec172f48eefa2237dc0c16919fbb2e726b39a65, frontend 427ca23a433a20be25b1f4373f32c9e1f6f8c400; оба 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 и пользовательская база не менялись.
  • 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 требует отдельного финального сравнения.
  • 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 не переписаны.

Если для устранения подтверждённого 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.
  • 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) и условие оптимизации.
  • 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 даёт конфликт, две независимые успешные траты сохраняются обе.
  • 2.4 [backend] После 2.3 реализовать перевод одной записью с проверкой обеих карт и дат начала учёта, двумя проекциями истории и общим денежным эффектом.

    • Covers: manual-bank-cards — Перевод между своими картами как одно действие; manual-bank-cards — Даты начала учёта и ручных операций; manual-bank-cards — Изоляция пользовательских финансовых данных.
    • Verification: реальная DB-проверка подтверждает обе стороны перевода, допустимый отрицательный остаток источника и отсутствие частичного результата при ошибке; отклоняются одинаковые, чужие и архивные карты и дата до начала учёта любой стороны. Сумма не включается в расходы одной или всех карт.
  • 2.5 [backend] После 2.3 реализовать связанные частичные и повторные возвраты, наследование категории покупки, общий лимит и чтение доступных исходных расходов за любой период.

    • Covers: manual-bank-cards — Возврат связан с исходным расходом; manual-bank-cards — Согласованные изменения и защита повторной отправки; manual-bank-cards — Изоляция пользовательских финансовых данных.
    • Verification: DB cases проверяют несколько возвратов, исходный расход прошлого месяца, чужую/удалённую покупку, дату до покупки и два конкурирующих возврата с превышением общего лимита. Повтор успешно сохранённого полного возврата после потерянного ответа возвращает существующий результат без ошибки нового лимита и без дубликата.
  • 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 с уменьшением покупки сохраняет общий лимит.
  • 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 архивированной карты возвращает ту же архивную карту.

Результат раздела 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.
  • 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 не попадают в ответы с ошибками.
  • 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.
  • 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.

Результат раздела 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-контракты сохранены.
  • 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 отсутствуют.

Результат 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; сводка всех карт включает архив независимо от фильтра списка.
  • 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 без собственной финансовой арифметики.
  • 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.
  • 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 полного возврата и сохранение формы без ложного успеха.
  • 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 и обратимый архив. После успешного действия все затронутые видимые суммы соответствуют новым серверным данным.
  • 5.6 [frontend] После 5.3 добавить управление начальными и своими категориями и создание категории из формы расхода без потери введённой операции.

    • Covers: manual-bank-cards — Общие для пользователя категории расходов; manual-bank-cards — Ручное внесение расходов и пополнений; manual-bank-cards — Доступные формы и различимые состояния без ложного успеха.
    • Verification: RTL/MSW проверяет add/rename, уникальность без регистра и длину, переименование default category без утраты роли, обновление названий в истории/сводке и неизменный черновик расхода при добавлении категории. Удаление и вложенные подкатегории отсутствуют согласно scope.

Результат 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 не подменяет браузерную проверку.
  • 6.2 [docs] После подтверждения реализованного поведения обновить документацию: область банковских карт, глоссарий, обзор продукта и тематическую навигацию, хранимые данные, денежные правила и безопасное восстановление.

    • Covers: N/A — as-built объяснение поставленного поведения и восстановления из Delivery Map; новая норма не вводится и не копируется параллельно Delta Specs.
    • Verification: пройти путь README → банковские карты → понятия/расчёты/исправления и восстановление; сверить текст с поставленными flows и ограничениями, включая ручной источник баланса, отрицательные итоги, архив, повторы и сохранение новой истории при rollback. Ссылки ведут на существующие targets; исторические материалы не переписываются, обещания неподтверждённой миграции не добавляются.

Результат 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-проверка не запускалась успешно.
  • 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 не заменяют его.
  • 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; использовать актуальный frontend openapi:check из 7.2, не повторяя его при неизменном snapshot/types. Проверка не требует T-Bank и не изменяет snapshot автоматически.
  • 7.4 [docs] После 6.2 выполнить canonical docs gate, ручную смысловую сверку и проверку затронутых маршрутов чтения.

    • Covers: N/A — проверка связности as-built документации из Delivery Map, без самостоятельного нормативного поведения.
    • Verification: из docs выполнить npm run verify; проверить новые Markdown-файлы и затронутые внешние относительно docs ссылки. Если изменены Mermaid-диаграммы, отдельно проверить доступным локальным renderer их вид либо явно сохранить ограничение; новый стек для этого не устанавливать.
  • 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 и завершение реализации не выводятся только из наличия файлов.

Независимая проверка результата и завершение 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 остаётся прежним.