fix(v2): use payment_hash as settlement idempotency key
The initial m005 made bitspire_event_id the UNIQUE idempotency key on dca_settlements, but settlements arriving through LNbits' invoice listener (the canonical path per nostr-transport-branch architecture) don't carry a Nostr event id at the Payment level — that's the underlying transport's concern, not exposed to extensions. The natural unique key is payment_hash: - every LN invoice has a globally unique payment_hash - subscription replays / dispatcher double-fires dedup via UNIQUE - it's always present on the Payment object the invoice_listener delivers Reshape the dca_settlements column constraints: - payment_hash: TEXT NOT NULL UNIQUE (was: NOT NULL + separate index) - bitspire_event_id: TEXT (was: NOT NULL UNIQUE) — kept nullable for a future path where we subscribe to raw kind-21000 Nostr events directly, bypassing the Payment system Also rename the CRUD helper: get_settlement_by_event_id → get_settlement_by_payment_hash, and update create_settlement_idempotent to dedup on payment_hash. CreateDcaSettlementData / DcaSettlement adjust accordingly. The schema is unshipped (v2-bitspire branch is local only) — fixing m005 in-place is appropriate. The separate dca_telemetry path for kind-30078/30079 events already uses (machine_id, beacon_received_at) semantics, so the UNIQUE-by-Nostr-event-id pattern isn't needed there either. Caught during P1a design before subscribing to register_invoice_listener. Refs: aiolabs/satmachineadmin#9, aiolabs/lamassu-next#44 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
937749f149
commit
cba327d0f0
3 changed files with 34 additions and 29 deletions
|
|
@ -185,9 +185,9 @@ class UpdateDepositStatusData(BaseModel):
|
|||
|
||||
class CreateDcaSettlementData(BaseModel):
|
||||
machine_id: str
|
||||
bitspire_event_id: str # nostr event id — the idempotency key
|
||||
payment_hash: str # the idempotency key (UNIQUE in the dca_settlements table)
|
||||
bitspire_event_id: Optional[str] = None # reserved for direct-Nostr ingestion
|
||||
bitspire_txid: Optional[str] = None
|
||||
payment_hash: str
|
||||
gross_sats: int
|
||||
fiat_amount: float
|
||||
fiat_code: str = "GTQ"
|
||||
|
|
@ -205,9 +205,9 @@ class CreateDcaSettlementData(BaseModel):
|
|||
class DcaSettlement(BaseModel):
|
||||
id: str
|
||||
machine_id: str
|
||||
bitspire_event_id: str
|
||||
bitspire_txid: Optional[str]
|
||||
payment_hash: str
|
||||
bitspire_event_id: Optional[str]
|
||||
bitspire_txid: Optional[str]
|
||||
gross_sats: int
|
||||
fiat_amount: float
|
||||
fiat_code: str
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue