refactor(core): centralize mint quote claimability - #403
Conversation
🦋 Changeset detectedLatest commit: 9dea02a The changes in this PR will be included in the next version bump. This PR includes changesets to release 8 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #403 +/- ##
==========================================
+ Coverage 92.63% 93.37% +0.73%
==========================================
Files 111 112 +1
Lines 17633 17816 +183
==========================================
+ Hits 16334 16635 +301
+ Misses 1299 1181 -118
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9dea02a661
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ); | ||
| } | ||
| if (!quote.reusable) { | ||
| const siblings = await this.mintOperationRepository.getByQuoteId(mintUrl, method, quoteId); |
There was a problem hiding this comment.
Normalize the quote URL before loading sibling operations
When a plugin calls claimMintQuote with an equivalent but non-canonical URL such as https://mint.test/, the quote lookup succeeds because mint-quote repositories normalize URLs, but every MintOperationRepository.getByQuoteId implementation compares the supplied URL exactly. The resulting empty siblings list omits finalized issuance and executing reservations, so reusable-quote claimability can be overstated and an additional issuance operation may be created. Normalize mintUrl at entry or query with the canonical quote.mintUrl.
AGENTS.md reference: AGENTS.md:L160-L165
Useful? React with 👍 / 👎.
| ); | ||
| return { | ||
| observedRemoteStateAt, | ||
| quoteSnapshot: quote, |
There was a problem hiding this comment.
Validate locked quote ownership before persisting the snapshot
For a locked BOLT11 operation, if polling returns a missing or different pubkey together with monotonic paid accounting, this snapshot is persisted and can classify the operation as ready; execution then signs against the quote using the operation's old key. BOLT12/on-chain pending checks and BOLT11 recovery already reject this ownership contradiction, so checkPending should perform the same comparison before returning quoteSnapshot.
AGENTS.md reference: AGENTS.md:L162-L163
Useful? React with 👍 / 👎.
| : amountPaid.greaterThan(amountIssued) | ||
| ? 'PAID' | ||
| : 'ISSUED'; |
There was a problem hiding this comment.
Project overpaid issued BOLT11 quotes as issued
When a fixed quote for 10 units reports amountPaid = 11 and amountIssued = 10, claimability correctly treats it as complete, but this comparison projects its compatibility state as PAID because paid remains greater than issued. Both getMintQuoteRemoteState and mintQuoteToMethodSnapshot expose that incorrect projection, so compatibility consumers can treat an already-issued atomic quote as redeemable; valid nonzero BOLT11 issuance should project as ISSUED even when the payment was excessive.
Useful? React with 👍 / 👎.
Summary
Why
Runtime claimability had multiple competing decision paths across handlers, orchestration, watchers, processors, and repositories. Stacking #398 directly on #400 exposed additional races and ordering problems where raw or stale observations could override canonical accounting.
This replacement keeps one common claimability seam while retaining #400's protocol-specific security behavior.
Impact
Mint quote scheduling, execution, recovery, and pending selection now use the same canonical accounting policy. BOLT11 remains atomic, while BOLT12 and on-chain quotes retain reusable balance semantics. Compatibility
stateremains limited to import and projection behavior.Validation
Docker-backed live-mint integration could not run locally because Docker and
MINT_URLare unavailable; those workflows remain for CI.Stack
masterand rerun CI.Closes #387.
Supports #365.