feat(finance): billing-audit skill — money invariants C6

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-05-20 09:31:30 +03:00
parent fee8efc809
commit 2a73ee0cfe
4 changed files with 117 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
---
name: billing-audit
description: Аудит денежной корректности биллинг-кода Лидерры — money-инварианты при правке/ревью списаний, тарифов и баланса. Используй при «проверь списание», «аудит биллинга», «не теряются ли копейки», «идемпотентно ли списание», «корректна ли тарифная ступень», «что значит дрейф CsvReconcile», «провенанс charge_source». НЕ для моделирования процесса (process-modeling), поиска узких мест (process-analysis), security-аудита (D3), РСБУ/налогов (ru-tax-accounting), метрик выручки (product-management).
---
# Billing Audit — аудит денежной корректности биллинга Лидерры
Проектный скил раздела C6 карты «Финансы — биллинг и тарификация». Проверяет
**денежные инварианты** биллинг-подсистемы при правке или ревью кода. Объект —
корректность *начисления* (не процесс, не безопасность, не учёт/налоги).
## Когда использовать
- Правка/ревью кода в `app/app/Services/Billing/**`, `app/app/Jobs/Supplier/CsvReconcileJob.php`,
моделей `PricingTier`/`LeadCharge`, контроллеров биллинга.
- Вопрос «безопасно ли это денежно?» по списанию, тарифу, балансу, сверке.
## Процедура аудита (5 инвариантов)
Полный чек-лист с проверками и ссылками на файлы — `references/invariants.md`.
1. **Сохранение суммы** — все денежные операции через `bcmath` (bcadd/bcsub/bcmul/bcdiv,
scale фиксирован), никаких float; prepaid→₽ конвертация без потери копеек.
2. **Идемпотентность списания** — один лид = одно списание; повтор/ретрай джоба
не дублирует начисление (проверить уникальный ключ / advisory-lock / upsert).
3. **Корректность тарифной ступени**`PricingTierResolver` выбирает верную из 7
ступеней по объёму; границы ступеней (включительно/исключительно) однозначны.
4. **Дрейф сверки**`CsvReconcileJob` порог >5%: что сравнивается, что значит дрейф,
куда смотреть (рассинхрон поставки vs ошибка тарифа).
5. **Провенанс charge_source** — каждое списание имеет прослеживаемый источник
(`charge_source`); ручные/авто/CSV-восстановленные различимы.
## Границы
-`process-modeling` #52 / `process-analysis` #53 — те про *поток/процесс*; billing-audit про *деньги в коде*.
- ≠ D3 audit-security (#39/#40) — те про *безопасность*; billing-audit про *денежную корректность*.
-`ru-tax-accounting` #63 — тот про *учёт/налоги* (выход биллинга → налоговая база); billing-audit про *начисление*.
-`product-management:metrics-review` #42 — тот про *метрики выручки*; billing-audit про *корректность*.
## Связано
- Reuse: Boost #10 (модели), Pest #18 (тесты инвариантов), Larastan #12 (bcmath/без float), Sentry #34 / Redis #35 (runtime/очередь).
- ADR-012 (граница finance-tooling C6/C7).
@@ -0,0 +1,22 @@
{
"skill": "billing-audit",
"positive": [
"проверь корректность списания за лид",
"аудит денежной логики биллинга",
"не теряются ли копейки в prepaid→рублёвом балансе",
"идемпотентно ли списание при ретрае",
"правильно ли резолвится тарифная ступень",
"что значит дрейф >5% в CsvReconcile",
"проверь провенанс charge_source",
"ревью PricingTierResolver на ошибки округления",
"ledger двойной баланс — где может утечь сумма",
"audit charge invariants before merge"
],
"near_miss": [
{"prompt": "смоделируй BPMN процесса списания", "expect": "process-modeling #52"},
{"prompt": "где узкое место в воронке оплат", "expect": "process-analysis #53"},
{"prompt": "security-аудит платёжного эндпоинта", "expect": "D3 audit-security / Semgrep"},
{"prompt": "посчитай РСБУ-проводки по выручке", "expect": "ru-tax-accounting #63"},
{"prompt": "метрика MRR за месяц", "expect": "product-management metrics-review #42"}
]
}
@@ -0,0 +1,46 @@
# Денежные инварианты биллинга Лидерры — чек-лист аудита
Объект-файлы (на момент 20.05.2026):
- `app/app/Services/Billing/PricingTierResolver.php` — резолюция 7 ступеней (pure).
- `app/app/Services/Billing/LedgerService.php` — двойной баланс prepaid→₽ (bcmath).
- `app/app/Services/Billing/BillingTopupService.php` — пополнение.
- `app/app/Services/Billing/ChargeResult.php` — DTO результата списания.
- `app/app/Models/PricingTier.php`, `app/app/Models/LeadCharge.php`.
- `app/app/Repositories/PricingTierRepository.php`.
- `app/app/Jobs/Supplier/CsvReconcileJob.php` — hourly сверка, алерт дрейфа >5%.
- `app/app/Http/Controllers/Api/{AdminPricingTiersController,AdminBillingController,BillingController,TenantChargesController}.php`.
## I1. Сохранение суммы (bcmath, без float)
- [ ] Все арифметические операции с деньгами — `bcadd`/`bcsub`/`bcmul`/`bcdiv`/`bccomp` с явным `scale`.
- [ ] Нет `+`/`-`/`*`/`/` над денежными значениями (Larastan/grep на float-арифметику в Billing).
- [ ] prepaid→₽: конвертация округляет детерминированно (TRUNC/округление вниз в пользу tenant — свериться с кодом), сумма prepaid + ₽ не «исчезает».
- [ ] Денежные колонки — целочисленные копейки или DECIMAL, не float/double.
## I2. Идемпотентность списания
- [ ] Один лид → одно списание: уникальность по (lead_id) или advisory-lock в `LedgerService`.
- [ ] Ретрай `ImportLeadsJob`/`CsvReconcileJob` не создаёт дубль `lead_charges`.
- [ ] Транзакция + `lockForUpdate` на балансе при мутации (TOCTOU — см. Sprint 3 lockForUpdate).
## I3. Корректность тарифной ступени
- [ ] `PricingTierResolver` выбирает ступень по объёму `delivered_in_month` верно на границах.
- [ ] Границы ступеней непрерывны (нет дыр/перекрытий между 7 ступенями).
- [ ] Pest покрывает граничные значения (ступень N → N+1).
## I4. Дрейф сверки CsvReconcile
- [ ] Порог >5% — что сравнивается (поставка поставщика vs начислено) → `supplier_csv_reconcile_log`.
- [ ] Дрейф = рассинхрон поставки (норм) ИЛИ ошибка тарифа (баг) — различить по `charge_source`.
## I5. Провенанс charge_source
- [ ] Каждое `lead_charges.charge_source` заполнено и прослеживаемо.
- [ ] Авто/ручное/CSV-восстановленное (`recovered_from_csv_at`) различимы.
## Reuse-инструменты
Boost #10 (Eloquent-introspection), Pest #18 + pest-parallel-debugger (тесты + race),
Larastan #12 (статанализ bcmath), Sentry MCP #34 (runtime списаний), Redis MCP #35 (очередь сверки), context7 #60 (доки bcmath).
+6
View File
@@ -1509,3 +1509,9 @@ GAAP
ретрай
субледжер
хардкодит
# finance-tooling C6+C7 — billing-audit skill (2026-05-20)
TOCTOU
bcadd
bcsub
bcmul