[CL-1176] E2E money-путей: 3 латентных ledger-бага (auto-match NUMERIC, regulatoryRegime default, amount-constraint) #1186
No reviewers
Labels
No labels
ci-failing
duplicate
needs-rebase
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
europa-tech-srl/europatech!1186
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/cl-1176-e2e-latent-ledger-bugs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что сделано
Третий адверсариальный проход: синтетический ПОЛНЫЙ P2P-цикл (SELL → BUY → auto-match → escrow REFUNDED → unwind) на эфемерной копии prod-схемы (все 250 миграций), без моков money-путей. Первое реальное исполнение ledger-кода поймало 3 латентных бага:
counter.pricePerShareшёл вmulEur()безtoNum(), isFinite-guard превращал результат в 0. Каждый матч записал бы trade с totalPrice=0: продавец получает 0, покупатель уже дебетован полной суммой. Фикс:toNum()вauto-match.ts, honest-типCounterOrderRow(number | string), red-green тестauto-match.raw-numeric.test.ts(НЕ мокает decimal.js — замоканный mulEur прятал баг).transaction.createвне travel-rule путей не пишут колонку: любая ledger-запись падала null constraint violation. Миграция20260722150000_unblock_ledger_writes:SET DEFAULT '{}'+@default([])в схеме.amount <> 0(знак несёт направление).Opt-in E2E-тест закреплён:
revert.e2e.int.test.ts(гейтE2E_DATABASE_URL, снимает глобальные prisma/config-моки черезvi.unmock; в юнит-прогонах и CI — skip). Vault:api-p2p.md.Зачем
Все три бага латентны ТОЛЬКО потому, что prod pre-launch (transactions пуста, P2P-активности 0). Первый реальный пользовательский поток — покупка, payout, P2P-матч — упал бы или (хуже) тихо записал трейд на 0 с потерей денег покупателя. Юнит-тесты слепы к этому классу: prismaMock не знает DB constraints, замоканный mulEur коэрцит строки.
План тестирования
prisma migrate deployчистой миграции). Точная сверка каждой ноги: продавец 1000→1980→1000, покупатель 2000→1000→2000, система 0→20→0, basis 700 восстановлен, W15-B1.5 zero-basis, 3 reversing-строки ledger, идемпотентность already-applied, ордер не реанимирован (#1176).auto-match.raw-numeric.test.tsкрасный до фикса (expected +0 to be 500), зелёный после.Где могу ошибаться
@default([])) — требует твоего sign-off, сам НЕ мержу.amount <> 0vs «переписать 13+ мест на положительные суммы + направление типом»: взял меньший дифф, совместимый с существующим кодом. Если хочешь строгий положительный ledger — это отдельный большой рефакторинг.[]означает «регуляторный режим не проставлен» для всех обычных транзакций — если compliance-логика где-то будет считать пустой массив «нарушением», надо будет заполнять на write-путях.Синтетический полный P2P-цикл (SELL→BUY→auto-match→REFUNDED→unwind) на копии prod-схемы впервые исполнил money-путь без моков и поймал: 1) auto-match: pg driver adapter отдаёт NUMERIC из $queryRaw строками; counter.pricePerShare без toNum() валил mulEur() в 0 (isFinite-guard) — каждый матч писал бы trade с totalPrice=0 (продавцу 0, покупатель уже дебетован). Фикс + honest тип CounterOrderRow + red-green тест. 2) transactions.regulatoryRegime NOT NULL без default — ~60 мест transaction.create вне travel-rule не пишут колонку: любая ledger-запись падала бы. Миграция: SET DEFAULT '{}'. 3) check_transaction_amount_positive (amount>0) против >=13 мест кода, пишущих дебеты отрицательными (payouts/buyback/exchange/unwind). Миграция: constraint -> amount<>0. Всё латентно только потому, что prod pre-launch: transactions пуста. Opt-in E2E-тест закреплён (гейт E2E_DATABASE_URL, в CI skip).