feat(v2): partial-dispense + operator notes on settlements (P3d)
Closes the v1 feature request satmachineadmin#3 (partial transaction
processing) and adds operator-authored audit notes on settlements.
Schema (m006_add_settlement_notes):
ALTER TABLE dca_settlements ADD COLUMN notes TEXT
The notes column is append-only (prepend with timestamp, never edit in
place). Stores both system-generated audit memos (partial-dispense
recompute provenance) and operator-authored free-form notes (cash-
drawer reconciliation context, off-LN refund records, etc.).
Partial-dispense endpoint:
POST /api/v1/dca/settlements/{id}/partial-dispense
body: PartialDispenseData {dispensed_fraction OR dispensed_sats, notes}
Recompute path (in distribution.apply_partial_dispense_and_redistribute):
1. Refuse if any leg has status='completed' (Lightning can't claw back)
2. Resolve new_gross from dispensed_fraction or dispensed_sats
3. Linear-scale net/commission/fiat — preserves the original commission
ratio exactly; only rounding may drift by 1 sat
4. Re-stage-1 split using the CURRENT super_fee_pct (super may have
changed the rate since the original landed)
5. Build a memo capturing original values + reason + new values
6. Void pending/failed legs (status → 'voided')
7. Overwrite the settlement's monetary fields + prepend memo to notes
8. Reset status to 'pending' → process_settlement re-runs distribution
Operator notes endpoint:
POST /api/v1/dca/settlements/{id}/notes
body: AppendSettlementNoteData {note}
Each operator note is timestamped (UTC) and tagged with the author's
user_id so the audit trail is accountable. Non-empty, max 2000 chars.
72/72 tests still pass. 30 routes total. The full-directory ruff number
ballooned to ~500 because it includes legacy transaction_processor.py
(orphaned, not imported anywhere) and other v1 cruft on the branch.
Files I actively maintain are clean.
Note: a richer queryable audit history (filter by author / time range /
action type / etc.) is being tracked as a separate future-work issue.
The notes-column approach here is the v1 audit story; the dedicated
history table will be additive.
Refs: aiolabs/satmachineadmin#9, closes #3 (in spirit, marked
once verified end-to-end)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e8dcbfe26e
commit
2883eb7b79
5 changed files with 352 additions and 3 deletions
27
models.py
27
models.py
|
|
@ -224,6 +224,11 @@ class DcaSettlement(BaseModel):
|
|||
error_message: Optional[str]
|
||||
processed_at: Optional[datetime]
|
||||
created_at: datetime
|
||||
# Append-only audit memo. Populated when an operator triggers an in-place
|
||||
# adjustment (partial-dispense, manual reconciliation override). Each
|
||||
# entry timestamped + records original values so the overwrite is
|
||||
# auditable from the settlement detail view alone. Never edited in place.
|
||||
notes: Optional[str] = None
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -397,6 +402,28 @@ class PartialDispenseData(BaseModel):
|
|||
return v
|
||||
|
||||
|
||||
class AppendSettlementNoteData(BaseModel):
|
||||
"""Operator-authored free-form note on a settlement.
|
||||
|
||||
Notes are prepended (newest first) to the settlement's `notes` column,
|
||||
with a UTC timestamp and the author's user id so each entry is
|
||||
accountable. Useful for cash-drawer reconciliation context, off-the-
|
||||
record refund records, or any narrative an operator wants to attach
|
||||
for future reference.
|
||||
"""
|
||||
|
||||
note: str
|
||||
|
||||
@validator("note")
|
||||
def non_empty(cls, v):
|
||||
v = v.strip() if isinstance(v, str) else v
|
||||
if not v:
|
||||
raise ValueError("note cannot be empty")
|
||||
if len(v) > 2000:
|
||||
raise ValueError("note too long (max 2000 chars)")
|
||||
return v
|
||||
|
||||
|
||||
class SettleBalanceData(BaseModel):
|
||||
"""Resolves satmachineadmin#4 — operator settles small remaining LP balance
|
||||
from their own wallet at the current exchange rate."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue