Skip to content

Apply 1.0 freeze-required API fixes (non_exhaustive, ShortIdError, OutputSubstitution, must_use)#1703

Draft
spacebear21 wants to merge 4 commits into
payjoin:masterfrom
spacebear21:api/1.0-freeze-fixes
Draft

Apply 1.0 freeze-required API fixes (non_exhaustive, ShortIdError, OutputSubstitution, must_use)#1703
spacebear21 wants to merge 4 commits into
payjoin:masterfrom
spacebear21:api/1.0-freeze-fixes

Conversation

@spacebear21

@spacebear21 spacebear21 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

I ran a 1.0 API audit with Claude that surfaced these relatively low-hanging fruit issues that are best addressed before a 1.0 freeze.

Each commit is standalone:

  1. Mark public enums non-exhaustive — the receive/send session
    state/event/status/outcome enums, ReceiveSession/SendSession,
    ProtocolError, IntoUrlError, UrlParseError, ShortIdError, Version,
    MaybePayjoinExtras, and the persist transition/outcome enums. Adds the
    required wildcard arms in payjoin-cli (graceful "unknown" fallbacks in
    display and dispatch) and payjoin-ffi (unreachable!() in the infallible
    mirror-conversion From impls, which are version-locked to payjoin).
  2. Implement Error + Display for ShortIdError so it can be
    ?-propagated — it is the Err type of ShortId's TryFrom/FromStr but
    derived only Debug.
  3. Export OutputSubstitution under v2 — it was gated on the v1 feature,
    but v2 methods return it and v2 does not enable v1, so default (v2-only)
    builds could not name the type.
  4. Mark the persist transition types #[must_use] so dropping a transition
    without .save() is a compiler warning instead of a silently lost step.

Follows #1702 (bitcoin-ohttp / bitcoin-hpke insulation). Tracking: #976.

Disclosure: co-authored by Claude Code (Opus 4.8)

🤖 Generated with Claude Code

Adding a variant to a public exhaustive enum is a breaking change, so
without #[non_exhaustive] the crate could not grow these enums after 1.0
without a 2.0. Several of them are explicitly expected to grow (the
session event/state/status/outcome enums document planned additions).

Mark the public exhaustive enums non-exhaustive: the receive/send
session state, event, status, and outcome enums, ReceiveSession /
SendSession, ProtocolError, IntoUrlError, UrlParseError, ShortIdError,
Version, MaybePayjoinExtras, and the persist transition/outcome enums.

payjoin-cli and payjoin-ffi match several of these, so add wildcard arms
to keep the workspace compiling: graceful "unknown" fallbacks in the CLI
(display and dispatch), and unreachable!() in the FFI's infallible
mirror-conversion From impls, which are version-locked to payjoin.
ShortIdError is the error type of ShortId's TryFrom<&[u8]> and FromStr
impls, but it derived only Debug. Without Display and std::error::Error
it could not be `?`-propagated into Box<dyn Error> or anyhow, forcing
callers to handle it specially.

Implement Display and Error with source() chaining to the wrapped
bech32 and slice-conversion errors.
The v2 API returns OutputSubstitution (Receiver<WantsOutputs>::
output_substitution and PayjoinExtras::output_substitution), but its
crate-root re-export was gated on the v1 feature. Since v2 does not
enable v1, default (v2-only) builds returned a value of a type callers
could not name or import.

Drop the v1 gate. The re-export lives inside the _core-gated core
module, so it is now available whenever v1 or v2 is enabled.
Every state-machine transition returns a transition wrapper whose
.save() both persists the session event and yields the next typestate.
Dropping the wrapper without calling .save() silently loses the event
and the state advance, with no diagnostic.

Add #[must_use] to the transition types so that dropping one is a
compiler warning.
@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 28559155426

Coverage decreased (-0.1%) to 85.616%

Details

  • Coverage decreased (-0.1%) from the base build.
  • Patch coverage: 23 uncovered changes across 3 files (0 of 23 lines covered, 0.0%).
  • 2 coverage regressions across 1 file.

Uncovered Changes

File Changed Covered %
payjoin-cli/src/app/v2/mod.rs 11 0 0.0%
payjoin/src/directory.rs 10 0 0.0%
payjoin-cli/src/app/config.rs 2 0 0.0%

Coverage Regressions

2 previously-covered lines in 1 file lost coverage.

File Lines Losing Coverage Coverage
payjoin-cli/src/app/v2/mod.rs 2 51.82%

Coverage Stats

Coverage Status
Relevant Lines: 15337
Covered Lines: 13131
Line Coverage: 85.62%
Coverage Strength: 355.25 hits per line

💛 - Coveralls

@spacebear21 spacebear21 added this to the payjoin-1.0 milestone Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants