feat(v2): record fee_mismatch_sats per settlement, Phase 1 (#38 4/5)
Phase-1 observability per coord-log §2026-06-01T07:00Z (option A locked: always record, no enforce_fee_match gate): fee_mismatch_sats = bitspire_fee_sats - (platform_fee_sats + operator_fee_sats) Positive = bitspire over-reported; negative = under-reported; zero = exact match. Recorded unconditionally on every settlement; WARN- logged via loguru only when |delta| > tolerance, where tolerance = max(1, int(principal_sats * 0.001)) — 1-sat floor with 0.1% relative ceiling. bitspire.py:parse_settlement: - Computes the delta after split_principal_based returns. - WARN log line carries bitspire_fee_sats / expected / delta / tolerance / principal / both fractions / tx_type / machine-npub prefix for triage queries. - Always stamps fee_mismatch_sats onto CreateDcaSettlementData. - Comment explains the pre-Layer-3 expectation: large deltas are expected while the ATM hardcodes 7.77% cash-out (aiolabs/lamassu- next#57); the data here will quiet once Layer 3 ships. crud.py:create_settlement_idempotent: extends the INSERT to persist the new column. Tests: - tests/conftest.py: `loguru_capture` fixture — loguru routes to a pre-bound stderr sink that pytest's caplog (stdlib only) misses and capsys can't see; the fixture adds a list-sink for the test's duration. Reusable for future log-behavior tests. - tests/test_fee_mismatch_recording.py: 8 cases covering exact-match zero delta, bitspire over- and under-reporting, the pre-Layer-3 large-delta scenario, within-tolerance silence, over-tolerance warning, diagnostic-fields presence in the WARN line, and the 1-sat floor on tiny-principal settlements. 164/164 tests green. Phase 2 (reject on out-of-tolerance) lands as a follow-up once observability data justifies the tighter posture. Refs: aiolabs/satmachineadmin#38 (Layer 1), coord-log §2026-06-01T07:00Z (lnbits advisory + option A lock). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
1babdfbf06
commit
d9e8a04b8b
4 changed files with 236 additions and 2 deletions
5
crud.py
5
crud.py
|
|
@ -601,13 +601,13 @@ async def create_settlement_idempotent(
|
|||
INSERT INTO satoshimachine.dca_settlements
|
||||
(id, machine_id, payment_hash, bitspire_event_id, bitspire_txid,
|
||||
wire_sats, fiat_amount, fiat_code, exchange_rate, principal_sats,
|
||||
fee_sats, platform_fee_sats, operator_fee_sats,
|
||||
fee_sats, platform_fee_sats, operator_fee_sats, fee_mismatch_sats,
|
||||
tx_type, bills_json, cassettes_json,
|
||||
status, error_message, created_at)
|
||||
VALUES (:id, :machine_id, :payment_hash, :bitspire_event_id,
|
||||
:bitspire_txid, :wire_sats, :fiat_amount, :fiat_code,
|
||||
:exchange_rate, :principal_sats, :fee_sats,
|
||||
:platform_fee_sats, :operator_fee_sats,
|
||||
:platform_fee_sats, :operator_fee_sats, :fee_mismatch_sats,
|
||||
:tx_type, :bills_json, :cassettes_json, :status,
|
||||
:error_message, :created_at)
|
||||
""",
|
||||
|
|
@ -625,6 +625,7 @@ async def create_settlement_idempotent(
|
|||
"fee_sats": data.fee_sats,
|
||||
"platform_fee_sats": data.platform_fee_sats,
|
||||
"operator_fee_sats": data.operator_fee_sats,
|
||||
"fee_mismatch_sats": data.fee_mismatch_sats,
|
||||
"tx_type": data.tx_type,
|
||||
"bills_json": data.bills_json,
|
||||
"cassettes_json": data.cassettes_json,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue