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>
32 lines
1,022 B
Python
32 lines
1,022 B
Python
"""
|
|
Pytest configuration for the satmachineadmin extension test suite.
|
|
|
|
Provides a `loguru_capture` fixture for tests that need to verify
|
|
loguru WARN/ERROR side-effects. Loguru attaches its default sink to
|
|
sys.stderr at import time, before pytest's `capsys` wraps stderr, so
|
|
neither `caplog` (stdlib logging only) nor `capsys` reliably sees
|
|
loguru output. The fixture adds a list-sink for the test's duration
|
|
and removes it on teardown.
|
|
"""
|
|
|
|
from typing import Generator, List
|
|
|
|
import pytest
|
|
from loguru import logger
|
|
|
|
|
|
@pytest.fixture
|
|
def loguru_capture() -> Generator[List[str], None, None]:
|
|
"""Capture loguru log records into a list for the test's duration.
|
|
|
|
Usage:
|
|
def test_warns_on_X(loguru_capture):
|
|
do_thing_that_warns()
|
|
assert any("expected message" in msg for msg in loguru_capture)
|
|
"""
|
|
captured: List[str] = []
|
|
handler_id = logger.add(
|
|
captured.append, level="WARNING", format="{level} {message}"
|
|
)
|
|
yield captured
|
|
logger.remove(handler_id)
|