Repository navigation
feat(payouts): explicit minimum deposit on destinations, reserves decided at payout time, destinations delete and reserves (release v1.8.0) - #191
Merged
Conversation
Pseudo-version until rail0-go is released with #79; the release guard refuses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…swer The gateway (main 161d3ff) requires a destination's minimum deposit as an explicit answer: a figure (min_amount) or the flag no_minimum: true, exactly one — 422 minimum_required for neither or a blank figure, minimum_conflict for both. - destinations add: --min-amount <decimal> (0 is an ordinary figure, never negative) or --no-minimum (no_minimum: true, never a 0). Neither: a prompt on a terminal (an empty answer is not accepted; "none" states the venue has none), a usage error (minimum_required) without one or with --agent, before any request. Both: usage error (minimum_conflict). The summary before the details confirmation states the figure or "none (no minimum at this venue)". - destinations update: --no-minimum sends no_minimum: true; --min-amount "" is refused locally; both are a conflict. A change of [figure, no_minimum] needs the details consent; re-sending the current answer does not. - list / get / add / update / enable / disable / confirm print a "minimum" companion field: the figure, "none" (no_minimum) or "not set" (a destination registered before the minimum was asked). Raw fields unchanged. - Hints for minimum_required and minimum_conflict. - Help, README, docs/cli + docs/man; tests against the fake gateway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ger marked breaking) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd reserves Follows rail0-gateway e615989 through rail0-go 5f91344 (rail0-go#79, pseudo-version v1.9.1-0.20261102160918-5f913446474d). - payouts destinations add / update: --reserve removed (the gateway no longer stores a reserve on the destination); update's 'nothing to update' message and help follow. - payouts send / prepare: --no-refund-reserve and --no-gas-reserve send keep_refund_reserve / keep_gas_reserve false for that payout only (refused with --proof). Both reserves are kept by default; the help says skipping one may make a later refund or capture fail. - send's confirmation shows the reserves kept back (or skipped) from GET .../reserves, best effort, and what 'all' comes to now; submit's shows the refund_reserve / gas_reserve the payout recorded. - payouts destinations delete <id>: soft delete behind the y/N / --yes gate. payouts destinations reserves <id>: balance, refund reserve with its payment count, gas reserve and allowance on native-gas chains, available; the gateway record with --json. - payouts destinations list --include-deleted. - insufficient_balance hint: after the reserves kept back. - docs/cli and docs/man regenerated, README and tests updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follows rail0-gateway be29f83 and rail0-go 4c24316: the destination kind changed nothing and is gone. rail0-go pinned to the PR branch's pseudo-version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gateway 50e309b allows one live destination per wallet, chain and token: a second address for the same payment method is now 409 payout_destination_exists (before, only the same address was). The error hint and the delete docs say so: delete the destination to register another address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gateway 2a08a95 requires a label on POST /payout_destinations (trimmed; blank is 422 label_required) and keeps it unique among the account's live destinations, ignoring case (409 payout_destination_label_taken); PATCH may not blank it. - destinations add: --label is required. A missing or blank label is a usage error (label_required) without a terminal or with --agent, before any request; on a terminal it is prompted for. The label is trimmed, sent, and shown in the confirmation summary. - destinations update: a blank --label is refused locally (label_required); a label is sent trimmed. - Hints for label_required and payout_destination_label_taken. - Help, README and generated docs: the label is required and unique per account (ignoring case); delete frees it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bumps [github.com/gorilla/websocket](https://github.com/gorilla/websocket) from 1.4.2 to 1.5.3. - [Release notes](https://github.com/gorilla/websocket/releases) - [Commits](gorilla/websocket@v1.4.2...v1.5.3) --- updated-dependencies: - dependency-name: github.com/gorilla/websocket dependency-version: 1.5.3 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
Merging pull request #191 publishes v1.8.0 through .github/workflows/release.yml.
marco-commercelayer
self-requested a review
November 4, 2026 10:36
marco-commercelayer
approved these changes
Nov 4, 2026
pviti
added a commit
that referenced
this pull request
Nov 4, 2026
…e ships (release v1.8.1) (#192) rail0-cli#191 merged as v1.8.0, but its release commit moved `go.mod` to rail0-go v1.10.0 without the matching `go.sum` entries. CI on the release commit stopped on `missing go.sum entry for module providing package github.com/commercelayer/rail0-go`, so nothing was tagged or published: v1.8.0 does not exist. A resume ("Run workflow") cannot fix it: the release workflow always builds the commit that SET the version (e72ceb8), which keeps the broken `go.sum`. So this PR carries the fix and a new version: **v1.8.1**, which ships everything from #191 (payout destinations with an explicit minimum, reserves decided at payout time, destinations delete and reserves, one destination per payment method, label required and unique, gorilla/websocket 1.5.3). The change: `go mod tidy` adds the rail0-go v1.10.0 checksums and drops the two stale pseudo-version lines. Gate run locally: gofmt, `go build ./...`, `go vet ./...`, `go test ./...`. Root cause, to fix separately: `bin/release-prepare` rewrites the rail0-go version in `go.mod` but does not refresh `go.sum`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- release:start --> ## rail0 CLI v1.8.1 <!-- release-notes:start --> ### Added - **payouts:** explicit minimum deposit on destinations, reserves decided at payout time, destinations delete and reserves (#191) ### Fixed - **deps:** go.sum entries for rail0-go v1.10.0, so the payouts release ships (#192) **Full diff:** v1.7.1...v1.8.1 <!-- release-notes:end --> --- **Version:** **1.8.1**, set by hand (`bin/release-prepare 1.8.1`); the computed bump would be **minor**. Merging this pull request also releases **v1.8.1**: its changes and the version bump ship together, under the one approval. On the push to `main`, `.github/workflows/release.yml` re-runs CI on the merge commit, creates the tag, and GoReleaser builds the binaries and publishes the GitHub release, and posts the release to Slack. The release notes are the text between the `release-notes` markers above, read from this pull request when it merges: edit them here, before merging. _Opened by `bin/release-prepare`._ <!-- release:end -->
pviti
added a commit
that referenced
this pull request
Nov 4, 2026
… (release v1.8.2) (#193) Root cause of the failed v1.8.0 release (#191): when `bin/release-prepare` offers to move `go.mod` to the latest rail0-go tag and you accept, it rewrote the version in `go.mod` as text and committed only `VERSION` and `go.mod`. CI on the release commit then stopped on `missing go.sum entry for module providing package github.com/commercelayer/rail0-go`, and the release workflow published nothing. #192 repairs `go.sum` and releases v1.8.1; this PR stops it from happening again. **Change** - After the `go.mod` bump: `go mod download <rail0-go>@vX.Y.Z`, `go mod tidy`, `go build ./...`. Each step aborts the run with a clear message if it fails, before anything is committed or pushed. - `go.sum` joins `VERSION_FILES`, so it is committed with the bump. It is also accepted by the "files outside the version bump" guard. - `bin/release-prepare-test`: `FILES` gains `go.sum`, so the fixture has it. Only `FILES` differs between the four repos' copies, so the shared script stays identical. **Checks:** `bash -n bin/release-prepare`; `bin/release-prepare-test` passes. The interactive bump path needs a terminal, so the test suite does not run it. I reviewed it by reading. No release: this is tooling only. It can merge before or after #192. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- release:start --> ## rail0 CLI v1.8.2 <!-- release-notes:start --> ### Fixed - **release:** release-prepare refreshes go.sum when it moves rail0-go (#193) **Full diff:** v1.8.1...v1.8.2 <!-- release-notes:end --> --- **Version:** **patch**, computed from the pull requests merged since v1.8.1 (a breaking change → major, `feat` → minor, anything else → patch). Decided by: - fix(release): release-prepare refreshes go.sum when it moves rail0-go (#193) Merging this pull request also releases **v1.8.2**: its changes and the version bump ship together, under the one approval. On the push to `main`, `.github/workflows/release.yml` re-runs CI on the merge commit, creates the tag, and GoReleaser builds the binaries and publishes the GitHub release, and posts the release to Slack. The release notes are the text between the `release-notes` markers above, read from this pull request when it merges: edit them here, before merging. _Opened by `bin/release-prepare`._ <!-- release:end -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gateway (main 161d3ff) now requires a payout destination's minimum deposit as an explicit answer: either a figure (
min_amount) or the flagno_minimum: true, exactly one. Neither, or a blank figure, gets 422minimum_required; both get 422minimum_conflict. This PR adds that to the CLI on top of rail0-go#79 (CreatePayoutDestinationRequest.MinAmount *Uint256String+NoMinimum bool, the same on update, andPayoutDestination.NoMinimum).rail0 payouts destinations add--min-amount <decimal>takes the venue's figure, converted with the token's decimals as before.0is an ordinary figure, and a negative value is refused up front.--no-minimummeans the venue has none. It sendsno_minimum: trueand never a0.nonestates the venue has none.--agentor no terminal, it is a usage errorminimum_required, raised before any request, telling you to look up the venue's deposit page.minimum_conflict, before any request.none (no minimum at this venue).rail0 payouts destinations update <id>--no-minimumsendsno_minimum: true, which removes a figure.--min-amount <decimal>sets a figure and clears the flag.--min-amount ""is refused locally (minimum_required). Passing both flags isminimum_conflict.[figure, no_minimum]pair asks for the details consent, the same y/N prompt or--confirm-detailsas before. Re-sending the current answer does not, which matches the gateway's comparison.Output
list,get,add,update,enable,disableandconfirmprint aminimumcompanion field. It is the figure (frommin_amount_formatted),nonewhenno_minimumis set, ornot setfor a destination registered before the minimum was asked. Raw fields are unchanged, and-qstill prints only the id.Hints
minimum_requiredandminimum_conflict, naming--min-amount/--no-minimum.payout_destination_minimum_unsetno longer exists in the gateway (destinations with no minimum stated are not blocked), so it has no hint andsend/submitsay nothing about it.Behaviour change
A script that calls
destinations addwithout a minimum now gets a usage error. The updated gateway refuses such a request anyway (minimum_required). This PR does not mark the change as breaking (no!, no footer): decide that when preparing the release.Tests
In
cmd/payouts_test.go, against the fake gateway:addwith neither flag, with both, or with a negative minimum is refused with the right code, and no request at all is sent.--no-minimumsendsno_minimum: trueand nomin_amount.--min-amount 0sends"0"without the flag. The summary is checked for both.update --min-amount ""is refused with no request.update --no-minimumneeds consent, then sendsno_minimum: true, no figure andconfirm_details; re-sending it on a destination that is alreadynonesends noconfirm_details. Both flags giveminimum_conflictwith no request.minimumfield is checked for a figure,0,noneandnot set, plus throughget.Gate run locally: gofmt,
go build ./...,go vet ./...,go test ./..., gendocs drift and theSOURCE_DATE_EPOCHclock check,sh -n install.sh,bin/release-prepare-test. README Payouts section, help text, docs/cli and docs/man are updated.Reserves decided at payout time, destinations delete and reserves (rail0-gateway e615989)
rail0-go bumped to the rail0-go#79 head 5f91344 (
v1.9.1-0.20261102160918-5f913446474d, no replace directive).payouts destinations add/update:--reserveremoved — the gateway no longer acceptsreserve_amounton a destination. Breaking for scripts that passed it. Update's "nothing to update" message and the help text follow.payouts send/prepare:--no-refund-reserveand--no-gas-reservesendkeep_refund_reserve/keep_gas_reserve: falsefor that payout only (a usage error with--proof). Unset, nothing is sent and the gateway keeps both (its default). The help says both are kept by default and that skipping one may make a later refund or capture fail.send's confirmation shows the reserves kept back (or SKIPPED, with the risk) fromGET /payout_destinations/{id}/reserves(best effort: a failed read leaves the prompt without figures), and for--amount allwhat it comes to now.submit's confirmation shows therefund_reserve/gas_reservethe prepared payout recorded;prepareprints them with the payout.payouts destinations delete <id>: soft delete behind the same y/N /--yesgate asconfirm; prints the destination withdeleted_at.payouts destinations reserves <id>: balance, refund reserve with its refundable-payment count, gas reserve and gas allowance (native-gas chains only), available.--json(or a pipe /--agent) prints the gateway's record unchanged.payouts destinations [list] --include-deleted.insufficient_balancehint: "after the reserves kept back", pointing atdestinations reservesand the opt-out flags.docs/clianddocs/manregenerated withtools/gendocs; README Payouts section updated (new "Reserves (decided at payout time)" section, delete/reserves/--include-deleted).reserve_amountand--reserveis gone from add/update; reserve flags → request (unset / false / refused with proof); send with--no-refund-reserve; the send and submit prompts with the reserves (native gas, non-native, proof); delete gate and DELETE; reserves route, JSON output and terminal view;--include-deletedquery; command tree.Checks run locally: gofmt,
go build ./...,go vet ./...,go test ./..., docs freshness (go run ./tools/gendocs+ clean diff, also withSOURCE_DATE_EPOCH),sh -n install.sh, VERSION format,bin/release-prepare-test— all pass. golangci-lint is not configured in this repo.No destination kind (rail0-gateway be29f83)
The kind changed nothing at the gateway and the label already names the venue, so it is gone.
rail0 payouts destinations addloses--kind(and its completion); docs/cli and man pages regenerated.Kindand thePayoutDestinationKind*constants. Replace with the tag once rail0-go is released.Gate:
go build,go vet,go test ./...,bin/docs.One destination per payment method
Gateway
50e309b: a wallet has at most one live destination per token and chain. A second address for the same payment method is now409 payout_destination_exists(before, only the same address was). The error hint and the delete docs say so: delete the destination to register another address.Destination label required and unique
Gateway
2a08a95:POST /payout_destinationsrequireslabel(trimmed; blank is422 label_required), unique among the account's live destinations ignoring case (409 payout_destination_label_taken); deleting a destination frees its label.PATCHmay not blank it.payouts destinations add:--labelis required. Missing or blank (spaces only) is a usage errorlabel_requiredwithout a terminal or with--agent, before any request; on a terminal it is prompted for (blank answers refused). The label is trimmed, sent, and shown in the confirmation summary.payouts destinations update --label: blank is refused locally (label_required); the label is sent trimmed.label_requiredandpayout_destination_label_taken.delete.addtests now pass a label.gorilla/websocket 1.4.2 → 1.5.3 (folded in from #190)
The Dependabot bump from #190, cherry-picked here so the release ships from one pull request. It is an indirect dependency (
go.modandgo.sumonly), and 1.5.3 is the first patched version for the open Dependabot alert (weak PRNG for the WebSocket mask key). Gate after the cherry-pick: gofmt,go build ./...,go vet ./...,go test ./...,bin/release-prepare-test.🤖 Generated with Claude Code
rail0 CLI v1.8.0
Added
Full diff: v1.7.1...v1.8.0
Version: minor, computed from the pull requests merged since v1.7.1 (a breaking change → major,
feat→ minor, anything else → patch). Decided by:Merging this pull request also releases v1.8.0: its changes and the version bump
ship together, under the one approval. On the push to
main,.github/workflows/release.ymlre-runs CI on the merge commit, creates the tag, and GoReleaser builds the binaries and publishes the GitHub release, andposts the release to Slack.
The release notes are the text between the
release-notesmarkers above, read from thispull request when it merges: edit them here, before merging.
Opened by
bin/release-prepare.