refactor(v2): rename net_sats → principal_sats for semantic clarity

`net` is financial-accounting ambiguous (net of what?). In the
bitSpire/DCA context this column is specifically the principal the
operator distributes to LPs (gross − commission), not a generic net
amount. Renaming locally before any bitSpire firmware locks the
wire-level name; lamassu-next#44 should adopt the same name.

Scope:
- migrations.py: m003 ALTER TABLE … RENAME COLUMN, idempotent probe
  pattern matching m002. Also updates the m001 canonical schema so
  fresh installs land on the new column directly.
- models.py: `CreateDcaSettlementData.principal_sats` /
  `DcaSettlement.principal_sats`. Field-doc comment updated.
- bitspire.py: both happy path and fallback path return
  `principal_sats=…`. Reads `extra.get("principal_sats")` from the
  bitSpire payload (lamassu-next#44 should follow this rename).
- crud.py: INSERT column list + `apply_partial_dispense(
  new_principal_sats=…)` keyword.
- distribution.py: every `settlement.net_sats` → `settlement.
  principal_sats`; partial-dispense memo + helper signatures updated;
  the leg-order docblock at the top reads "principal_sats".
- tasks.py: landed-settlement log line.
- static/js/index.js: settlements-table column `principal_sats` with
  label "Principal (→ LPs)".
- templates/satmachineadmin/index.html: q-td key + binding.

All 86 unit tests still pass. No backwards-compat shim — v2-bitspire
isn't released; the rename is a clean break.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-05-15 23:21:32 +02:00
commit 1feaba80ed
8 changed files with 97 additions and 106 deletions

View file

@ -146,9 +146,9 @@ def _parse_extra(
super_fee_pct: float,
) -> CreateDcaSettlementData:
"""Happy path: bitSpire populated Payment.extra per lamassu-next#44."""
net_sats = _coerce_int(extra.get("net_sats"))
principal_sats = _coerce_int(extra.get("principal_sats"))
fee_sats = _coerce_int(extra.get("fee_sats"))
if net_sats is None or fee_sats is None:
if principal_sats is None or fee_sats is None:
# Missing key fields — shouldn't happen post-#44 but defensive.
return _parse_fallback(machine, payment_hash, gross_sats, super_fee_pct)
commission_sats = fee_sats
@ -170,7 +170,7 @@ def _parse_extra(
fiat_amount=fiat_amount,
fiat_code=fiat_code,
exchange_rate=exchange_rate,
net_sats=net_sats,
principal_sats=principal_sats,
commission_sats=commission_sats,
platform_fee_sats=platform_fee_sats,
operator_fee_sats=operator_fee_sats,
@ -193,7 +193,7 @@ def _parse_fallback(
base_amount = round(gross / (1 + commission_pct))
commission = gross - base_amount
"""
net_sats, commission_sats, _effective = calculate_commission(
principal_sats, commission_sats, _effective = calculate_commission(
crypto_atoms=gross_sats,
commission_percentage=machine.fallback_commission_pct,
discount=0.0,
@ -211,7 +211,7 @@ def _parse_fallback(
fiat_amount=0.0,
fiat_code=machine.fiat_code,
exchange_rate=0.0,
net_sats=net_sats,
principal_sats=principal_sats,
commission_sats=commission_sats,
platform_fee_sats=platform_fee_sats,
operator_fee_sats=operator_fee_sats,