Pre-1.0 Doorkeeper for SessionOutcome in#1747
Conversation
Coverage Report for CI Build 29564057454Coverage decreased (-0.03%) to 86.161%Details
Uncovered Changes
Coverage Regressions1 previously-covered line in 1 file lost coverage.
Coverage Stats
💛 - Coveralls |
There was a problem hiding this comment.
This seems like a nice path that leaves the door open for non-breaking 1.x Monitor fixes. However, there are 4 distinct components to this PR and I think each deserves standalone attention:
- ACK Reserve the
SessionOutcome::Othervariant - this is the actually useful part, but the justification in the docstring and commit message argues for the wrong thing. "binaries pinned to this persisted format can still parse event logs written by a later minor release that does emit it" is a fine side-effect but forwards-compatibility is not the thing we actually care about (even the docs in persist.rs say "Forward compatibility in general is not appropriate"). Backwards compatibility is the goal. The reason to reserveOtherisn't data compat at all, it's API semver: reserving the name now makes the classifier additive by construction. That argument doesn't appear in the PR. - cACK Change
SessionOutcome::Successto a unit variant. This one requires historical context: the original monitor (0c67af7) recorded an empty witness on the non-segwit path, the path where it actually would have mattered to store those as the only way to reconstruct the final payjoin transaction (see comment). #1218 then deleted that path entirely, so the stored event payload is indeed dead code now. However, #1692 would restore non-segwit detection, which would make this event payload undead once again. I think an argument can be made for only storing aSuccess(Txid)instead of the full script_sig/witnesses. This would also make this PR self-consistent: as written we record the txid of a transaction we don't recognize (Other(Txid)) and nothing for the payjoin we do. - NACK Make SessionOutcome
#[non_exhaustive]. This reverses 8c92050, which explicitly namedSessionOutcomein the keep-exhaustive list, without engaging with that rationale, so I'm not sure whether this is intentional or an accidental omission/hallucination. TheSessionOutcome::Othervariant already grants exactly one named extension. I think any additional unforeseen outcomes should break at compile time instead of leading to unexpected behavior (e.g. as written any future unrecognized outcome would render as "Session closed" in payjoin-cli, with no compile error). - NACK Add
success()andaborted()constructors on SessionOutcome. I don't understand the rationale for this. This seems to simply accomodate a payjoin-cli implementation detail for history display? I'm not even sure that implementation is correct, currently it looks like the sender just hardcodesaborted()it to display "Session aborted" if a replay error occurred.
b476aa0 to
506891d
Compare
The persisted SessionEvent format freezes at the payjoin-cli 1.0 database-backwards-compatibility commitment, so reshape the receiver's terminal SessionOutcome while a format break is still free. Change Success(Vec<(ScriptBuf, Witness)>) to Success(Txid). The witness payload was recorded so the receiver could reconstruct the final Payjoin on the non-segwit path, but payjoin#1218 removed that path entirely, leaving the enum payload as dead code. The Receiver settlement classifier (payjoin#1692) will restore non-segwit detection, which would make the payload live again, but sufficient record of a settlement is the txid of the transaction that settled it rather than the witness list. The wallet that observed the spend already holds the full transaction. Recording Success(Txid) also keeps the terminal variants consistent where the outcome for the transaction we recognize carries the same evidence as the one we do not. Add Other(Txid), mapped to SessionStatus::Failed, for contested outpoints settled by an unrecognized transaction. Nothing produces it yet. The reason to reserve it now is API semver, not data compatibility. 8c92050 deliberately kept SessionOutcome exhaustive. A wildcard match arm has no meaningful semantics for a terminal outcome, and the compile error on a new variant is a feature. So adding a variant after 1.0 would be a semver-breaking change that we want. Naming Other before the freeze makes the settlement classifier additive by construction while keeping the enum exhaustive. (Forward compatibility of the persisted data is explicitly not a goal. See the persist module docs, we want unknown state to error.) Update payjoin-cli to match the new shapes exhaustively. no wildcard arms, per 8c92050 surfacing the settlement txid in the history and cancel output, and pin the sealed JSON encodings of the terminal events in a serialization-shape test. StatusText becomes String rather than &'static str in order to accomodate the txid in format!.
506891d to
92dfe80
Compare
Adopted. docstring & commit message now refer to semver compat & exhaustive rationale so that we don't regress.
Adopted as suggested including the #1218 reference AND the rationale for only Txid in the variant in the commit history. It keeps it simpler to let an underlying wallet handle saving the witnesses while our lib only stores the Txid as a link to that wallet state.
Reverted as suggested, please ignore. payjoin-cli does seem limited here in that it presents Just one commit now. |
150 lines of release hygiene that seals the persisted
SessionOutcomeformat before 1.0 freezes itso that after 1.0's db compatibility commitment we can add terminal outcomes (like the settlement classifier's in #1692) additively in 1.x instead of via a semver break plus a db migration. no behavior changes, and the cost is one more rc.
Pre-change:
Co-authored by Claude Code
Pull Request Checklist
Please confirm the following before requesting review:
AI
in the body of this PR.