@@ -260,20 +260,20 @@ Purely additive. Touches no trade flow.
260260 -- Phase 3: counts ONLY `send_payment` retries against an invoice
261261 -- the counterparty has already submitted. Bumped only by step 6
262262 -- of the §8.1 scheduler loop. `payout_max_retries` is checked
263- -- against this counter alone — invoice-request DMs do NOT count
264- -- here (see `invoice_request_attempts` below).
263+ -- against this counter alone — invoice-request messages do NOT
264+ -- count here (see `invoice_request_attempts` below).
265265 payout_attempts integer not null default 0 ,
266- -- Phase 3: counts how many `Action::AddInvoice` DMs the scheduler
267- -- has sent asking the counterparty for a payout invoice. Bumped
268- -- by step 1 of §8.1. Bounded by the forfeit window
266+ -- Phase 3: counts how many `Action::AddInvoice` messages the
267+ -- scheduler has sent asking the counterparty for a payout invoice.
268+ -- Bumped by step 1 of §8.1. Bounded by the forfeit window
269269 -- (`payout_claim_window_days`), not by `payout_max_retries`, so
270270 -- a slow-responding counterparty cannot prematurely flip the
271271 -- bond to `Failed`.
272272 invoice_request_attempts integer not null default 0 ,
273- -- Phase 3: timestamp of the last `AddInvoice` DM . Drives the
274- -- `payout_invoice_window_seconds` cadence check ("don't re-DM
273+ -- Phase 3: timestamp of the last `AddInvoice` message . Drives the
274+ -- `payout_invoice_window_seconds` cadence check ("don't re-send
275275 -- before the window has elapsed"). Persisted so a daemon restart
276- -- doesn't trigger an immediate re-DM .
276+ -- doesn't trigger an immediate re-send .
277277 last_invoice_request_at integer ,
278278 locked_at integer ,
279279 released_at integer ,
@@ -525,7 +525,7 @@ changes — pure ergonomics.
525525Lands ** before Phase 2 on purpose** . Phase 2 introduces dispute
526526slashes and the ` BondResolution ` payload; once that ships and
527527operators flip ` enabled = true ` in production, every taker on every
528- bond-enabled node sees the bond DM . We want clients to have already
528+ bond-enabled node sees the bond message . We want clients to have already
529529adopted the clean API by then so the seller-as-taker case (§6.3)
530530never has to lean on memo parsing in the wild.
531531
@@ -554,7 +554,7 @@ never has to lean on memo parsing in the wild.
554554- ** ` mostrod ` changes** in ` src/app/bond/flow.rs::request_taker_bond `
555555 and the take handlers:
556556 - Replace ` Action::PayInvoice ` with ` Action::PayBondInvoice ` when
557- enqueuing the bond DM .
557+ enqueuing the bond message .
558558 - Set the order's status to ` Status::WaitingTakerBond ` while the
559559 bond is outstanding (instead of leaving it in ` Pending ` ). Add
560560 the NIP-69 mapping in ` nip33::create_status_tags ` :
@@ -602,7 +602,7 @@ never has to lean on memo parsing in the wild.
602602 preimage yet) and notifies its taker with ` Action::Canceled ` .
603603 Once a bond does win, the handler iterates every other still-
604604 ` Requested ` bond on the order, calls ` release_bond ` on each
605- (LND hold-invoice cancel + ` BondState::Released ` ), and DMs
605+ (LND hold-invoice cancel + ` BondState::Released ` ), and messages
606606 each loser an ` Action::Canceled ` . Only after this cleanup does
607607 it copy the winning bond's ` taker_* ` context onto the order
608608 and call ` resume_take_after_bond ` .
@@ -670,7 +670,7 @@ never has to lean on memo parsing in the wild.
670670### 6.5.2 Client compatibility
671671
672672- A client that only knows ` Action::PayInvoice ` will silently ignore
673- the bond DM after this phase ships, the bond will never lock, and
673+ the bond message after this phase ships, the bond will never lock, and
674674 the take will time out and release. No funds at risk, but the take
675675 fails. This is the expected behaviour for unknown-action handling
676676 per §14.2 ("Clients must handle unknown statuses gracefully") — it
@@ -687,7 +687,7 @@ never has to lean on memo parsing in the wild.
687687
688688### 6.5.3 Tests
689689
690- - Bond DM enqueues with ` Action::PayBondInvoice ` , not ` PayInvoice ` .
690+ - Bond message enqueues with ` Action::PayBondInvoice ` , not ` PayInvoice ` .
691691- Order's ** DB** status flips to ` WaitingTakerBond ` while the bond is
692692 outstanding, flips out to ` WaitingPayment ` /
693693 ` WaitingBuyerInvoice ` (per the existing trade flow) once the bond
@@ -738,7 +738,7 @@ never has to lean on memo parsing in the wild.
738738 guard ensures exactly one transition to ` Locked ` succeeds. The
739739 loser's handler observes ` rows_affected = 0 ` , calls
740740 ` cancel_hold_invoice ` on its own hash to release its taker's
741- HTLC without settling, and DMs ` Action::Canceled ` to its taker.
741+ HTLC without settling, and messages ` Action::Canceled ` to its taker.
742742 Net effect is identical to the staggered case; no double-lock
743743 and no settled HTLC for the loser.
744744- Seller-as-taker case: one ` PayBondInvoice ` followed by one
@@ -986,30 +986,35 @@ trade finalization must never wait on the payout.
986986 bolt11): ` settle_hold_invoice(preimage) ` , transition the bond
987987 to ` state = Forfeited ` , publish the audit event with
988988 ` outcome = forfeited ` , and stop. The node retains the full
989- ` amount_sats ` . No further DMs or ` send_payment ` runs.
989+ ` amount_sats ` . No further messages or ` send_payment ` runs.
990990 - Otherwise, proceed with the normal payout steps below.
991991 - Normal payout steps:
992992 1 . If no ` payout_invoice ` yet, and the cadence window has elapsed
993993 (i.e. ` last_invoice_request_at IS NULL ` or
994994 ` now - last_invoice_request_at >= payout_invoice_window_seconds ` ):
995- enqueue an ` Action::AddBondInvoice ` DM (mostro-core 0.11.2+)
995+ enqueue an ` Action::AddBondInvoice ` message (mostro-core 0.11.2+)
996996 to the recipient (see "Recipient resolution" below) asking for
997997 a bolt11 for the full ` counterparty_share_sats ` — the handler
998998 validates the invoice principal against ` counterparty_share_sats `
999999 with fee = 0, so the routing fee must come out of Mostro's
10001000 wallet, not the invoice principal. (The bonded user may use
10011001 the estimated routing fee as guidance when choosing a recipient
10021002 node, but it is not subtracted from the requested amount.)
1003- The DM ** must include the forfeit deadline** (e.g. "claim by
1004- <ISO timestamp > or your share will be forfeited") via a
1005- ` Payload::TextMessage ` body alongside the action, so the user
1006- knows the clock is running. Bump ` invoice_request_attempts `
1007- and set ` last_invoice_request_at = now ` . ** Do not touch
1008- ` payout_attempts ` ** — that counter only governs ` send_payment `
1009- retries (step 6); mixing the two would let a slow-responding
1010- counterparty exhaust ` payout_max_retries ` on invoice-request
1011- DMs alone and prematurely flip the bond to ` Failed ` . Bounding
1012- invoice requests is the forfeit window's job
1003+ The message carries ** only the structured request payload** — no
1004+ hardcoded human-readable text. The forfeit deadline is not
1005+ shipped inline: the client computes it locally from the slash
1006+ moment (observable on the order's audit trail) plus
1007+ ` bond_payout_claim_window_days ` , which Mostro advertises on the
1008+ kind-38385 info event (§13.1). Keeping the wire payload
1009+ text-free lets clients render the warning ("your share will be
1010+ forfeited in N days") in the user's own locale, and avoids
1011+ baking English copy into the daemon. Bump
1012+ ` invoice_request_attempts ` and set `last_invoice_request_at =
1013+ now` . **Do not touch ` payout_attempts`** — that counter only
1014+ governs ` send_payment ` retries (step 6); mixing the two would
1015+ let a slow-responding counterparty exhaust ` payout_max_retries `
1016+ on invoice-request messages alone and prematurely flip the bond to
1017+ ` Failed ` . Bounding invoice requests is the forfeit window's job
10131018 (` payout_claim_window_days ` ), not the retry budget's. The node
10141019 share never leaves Mostro's wallet, so it has no separate
10151020 invoice step.
@@ -1034,7 +1039,7 @@ trade finalization must never wait on the payout.
10341039 ` Forfeited ` (the user never gave us an invoice).
10351040
10361041 When ` slash_node_share_pct = 1.0 ` the counterparty leg is skipped
1037- entirely (no ` AddBondInvoice ` DM , no ` send_payment ` , no forfeit
1042+ entirely (no ` AddBondInvoice ` message , no ` send_payment ` , no forfeit
10381043 window to wait for); the bond goes straight from ` PendingPayout ` →
10391044 settle → ` Slashed ` after step 3.
10401045
@@ -1060,7 +1065,7 @@ trade finalization must never wait on the payout.
10601065 taker have active bonds, neither party deserves restitution
10611066 (§15.2 — "both behaved badly"). For each row, treat as
10621067 ` slash_node_share_pct = 1.0 ` for that payout: skip the
1063- ` AddBondInvoice ` DM , retain ` amount_sats ` in full, settle the
1068+ ` AddBondInvoice ` message , retain ` amount_sats ` in full, settle the
10641069 HTLC in step 3, transition to ` Slashed ` . (Phase 5+ wires this;
10651070 Phase 2's taker-only world cannot reach this branch.)
10661071
@@ -1101,7 +1106,7 @@ trade finalization must never wait on the payout.
11011106 driving from that point on is the counterparty payout.
11021107- ** Partial success: settle OK, counterparty ` send_payment ` failed.**
11031108 The bond state stays in ` PendingPayout ` with a best-effort retry. The
1104- winner is kept informed via periodic DMs . If retries exhaust, state
1109+ winner is kept informed via periodic messages . If retries exhaust, state
11051110 becomes ` Failed ` ; at that point Mostro is holding the counterparty
11061111 share (unavoidable with the HTLC already settled) and logs loudly.
11071112 The node share is unaffected — it was always going to stay. This is
@@ -1113,7 +1118,7 @@ trade finalization must never wait on the payout.
11131118 the scheduler settles the HTLC and transitions to ` Forfeited ` . No
11141119 manual operator action is needed — this is a normal terminal
11151120 state, designed-in. Default 15 days gives even users with sporadic
1116- Nostr presence ample time to see the DM and respond.
1121+ Nostr presence ample time to see the message and respond.
11171122- ** Non-blocking:** ` release_action ` , ` admin_settle_action ` , etc. return
11181123 success the moment the trade escrow resolves. Bond payout happens
11191124 later.
@@ -1128,7 +1133,7 @@ trade finalization must never wait on the payout.
11281133- Edge case ` slash_node_share_pct = 0.0 ` → behaviour identical to the
11291134 pre-split design (full counterparty payout).
11301135- Edge case ` slash_node_share_pct = 1.0 ` → settle the HTLC, no
1131- ` AddInvoice ` DM is enqueued, no ` send_payment ` runs, bond goes
1136+ ` AddInvoice ` message is enqueued, no ` send_payment ` runs, bond goes
11321137 straight to ` Slashed ` .
11331138- ** Persistence test** : a bond enters ` PendingPayout ` under
11341139 ` slash_node_share_pct = 0.5 ` ; before payout completes, simulate a
@@ -1343,7 +1348,7 @@ it. The workable strategies:
13431348 visible.
13441349
13451350We recommend ** (a)** . Acceptable cost: maker sees one extra ` add-invoice `
1346- DM at range-close if there were partial slashes.
1351+ message at range-close if there were partial slashes.
13471352
13481353The split is applied ** per child** (each child's ` slashed_share_sats `
13491354is split independently), so the audit event for each child carries its
@@ -1405,20 +1410,40 @@ Tests mirror Phase 4 from the maker side; the "no slash" rows in the
14051410
14061411### 13.1 Scope
14071412
1408- - Extend the Mostro info event (` src/nip33.rs::info_to_tags ` ) with the
1409- bond config snapshot so clients can show users what the node enforces
1410- before they trade:
1411- - ` bond ` (` enabled ` | ` disabled ` )
1412- - ` bond-apply-to ` (` take ` | ` create ` | ` both ` )
1413- - ` bond-slash-timeout ` (` true ` | ` false ` )
1414- - ` bond-amount-pct ` / ` bond-amount-floor `
1415- - ` bond-slash-node-share-pct ` (the operator's ` slash_node_share_pct ` ,
1416- so users know up-front how a slashed bond is split between the node
1417- and the winning counterparty).
1418- - ` bond-payout-claim-window-days ` (the operator's
1419- ` payout_claim_window_days ` , so users know how long they have to
1420- submit a payout invoice before forfeiting their share).
1421- - ** No ` bond-slash-dispute ` tag** : dispute slashes are solver-driven
1413+ - The Mostro info event (` src/nip33.rs::info_to_tags ` ) carries the
1414+ bond config snapshot so clients can show users what the node
1415+ enforces before they trade. ** The full set below is shipped in
1416+ Phase 3** alongside the payout flow itself — the
1417+ ` Action::AddBondInvoice ` message intentionally carries no
1418+ human-readable deadline text, so the wire payload alone is not
1419+ enough for a client to warn the user; the kind-38385 tags close
1420+ that gap and let every warning render in the user's locale. Tag
1421+ naming follows the snake_case convention used elsewhere in
1422+ ` info_to_tags ` (` mostro_version ` , ` hold_invoice_expiration_window ` ,
1423+ etc.). The set:
1424+ - ` bond_enabled ` (` true ` | ` false ` ) — ** always emitted** , including
1425+ on nodes where ` [anti_abuse_bond] ` is absent or `enabled =
1426+ false`. Disambiguates "feature off on this node" from "older
1427+ daemon that doesn't speak bond at all": the latter omits the tag
1428+ entirely, the former emits ` false ` . All remaining bond tags are
1429+ emitted only when this is ` true ` .
1430+ - ` bond_apply_to ` (` take ` | ` create ` | ` both ` ) — whether the user
1431+ needs to lock a bond as maker, taker, or both.
1432+ - ` bond_slash_on_waiting_timeout ` (` true ` | ` false ` ) — node policy:
1433+ can a bond be slashed for missing a waiting-state timeout, or
1434+ only by solver directive in a dispute?
1435+ - ` bond_amount_pct ` / ` bond_base_amount_sats ` — bond economics:
1436+ ` max(amount_pct * order_amount, base_amount_sats) ` .
1437+ - ` bond_slash_node_share_pct ` — fraction of a slashed bond retained
1438+ by the node (the rest goes to the winning counterparty). Lets the
1439+ user see up-front what they would actually receive.
1440+ - ` bond_payout_claim_window_days ` — number of days the winning
1441+ counterparty has, from ` slashed_at ` , to submit a payout invoice
1442+ before forfeiting their share. Clients add this to ` slashed_at `
1443+ to render the deadline ("you have N days to claim") in the user's
1444+ own locale; Mostro never ships that text inline on the
1445+ ` AddBondInvoice ` message itself.
1446+ - ** No ` bond_slash_dispute ` tag** : dispute slashes are solver-driven
14221447 per resolution, not a node-policy switch.
14231448- Update ` docs/admin_settle_order.html ` and ` admin_cancel_order.html `
14241449 upstream (` mostro.network/protocol/ ` ) with an "Optional payload —
0 commit comments