Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
3463265
Add unilateral exit quote/build methods to the SDK seam
sethforprivacy Aug 20, 2026
37d17c9
Add unilateral exit settings section and experimental feature gate
sethforprivacy Aug 20, 2026
06ac276
Add the unilateral exit record store with a one-active-exit constraint
sethforprivacy Aug 20, 2026
4d8004d
Add the unilateral exit service: quoting, funding discovery, and signing
sethforprivacy Aug 20, 2026
9a66fd1
Add the unilateral exit page behind Advanced settings
sethforprivacy Aug 20, 2026
895a7d2
Update docs and copy for the experimental unilateral exit
sethforprivacy Aug 20, 2026
a0288c9
chore(deps): Bump Breez.Sdk.Spark from 0.22.0 to 0.22.2
dependabot[bot] Aug 21, 2026
95f5bf6
Add AI disclosure section to README
sethforprivacy Aug 21, 2026
d932a21
Merge pull request #21 from sethforprivacy/claude/ai-use-disclaimer-r…
sethforprivacy Aug 21, 2026
377dcea
Diff withdrawal ids instead of counting a saturated listing window
sethforprivacy Aug 21, 2026
31f924f
Merge pull request #22 from sethforprivacy/flint-funded-regtest-withd…
sethforprivacy Aug 21, 2026
eef5100
Make the funded regtest job block pull requests
sethforprivacy Aug 21, 2026
004e670
Merge branch 'main' into dependabot/nuget/BTCPayServer.Plugins.Flint/…
sethforprivacy Aug 21, 2026
363bd83
Merge pull request #23 from sethforprivacy/flint-funded-regtest-blocking
sethforprivacy Aug 21, 2026
beca59a
Merge pull request #20 from sethforprivacy/dependabot/nuget/BTCPaySer…
sethforprivacy Aug 21, 2026
9a9d195
Release 0.1.4
sethforprivacy Aug 21, 2026
2925f09
Merge pull request #24 from sethforprivacy/release/v0.1.4
sethforprivacy Aug 21, 2026
ff48251
Address the v0.1.4 security review findings
sethforprivacy Aug 21, 2026
050ed6a
Address the quorum review of the security fixes
sethforprivacy Aug 21, 2026
4b7e0b5
Merge pull request #25 from sethforprivacy/flint-v0.1.4-sec-fixes
sethforprivacy Aug 21, 2026
a59c143
Release 0.1.4.1
sethforprivacy Aug 21, 2026
26a4b14
Merge pull request #26 from sethforprivacy/release/v0.1.4.1
sethforprivacy Aug 21, 2026
5c8efd7
Address the third external review pass
sethforprivacy Aug 22, 2026
e819c25
Address the quorum review of the third-pass fixes
sethforprivacy Aug 22, 2026
fb6513c
Merge pull request #27 from sethforprivacy/flint-review-pass-3
sethforprivacy Aug 22, 2026
19bc117
Release 0.1.5
sethforprivacy Aug 22, 2026
f71db69
Merge pull request #28 from sethforprivacy/release/v0.1.5
sethforprivacy Aug 22, 2026
85b31cd
Let a store set its own Breez API key on the Advanced page
sethforprivacy Aug 22, 2026
cdf95e1
Merge pull request #29 from sethforprivacy/flint-api-key-override-ui
sethforprivacy Aug 22, 2026
afc1460
Release 0.1.5.1
sethforprivacy Aug 22, 2026
6f044d7
Gate Breez SDK update PRs on upstream releases, not tags
sethforprivacy Aug 22, 2026
76fa4b2
Merge pull request #31 from sethforprivacy/flint-breez-update-release…
sethforprivacy Aug 22, 2026
361cd3b
Merge pull request #30 from sethforprivacy/release/v0.1.5.1
sethforprivacy Aug 22, 2026
f02316f
Never display the stored Breez API key on the Advanced page
sethforprivacy Aug 23, 2026
c64d41f
Merge pull request #32 from sethforprivacy/flint-api-key-no-echo
sethforprivacy Aug 23, 2026
6015c39
Release 0.1.5.2
sethforprivacy Aug 23, 2026
e85be53
Merge pull request #33 from sethforprivacy/release/v0.1.5.2
sethforprivacy Aug 23, 2026
d82970c
Close the two audit findings on superceded-invoice credit and cross-s…
sethforprivacy Aug 24, 2026
39aa8a2
Run the cross-store configuration sweep on the periodic reconciliatio…
sethforprivacy Aug 24, 2026
e3e6d3d
Merge pull request #35 from sethforprivacy/flint-store-bound-connecti…
sethforprivacy Aug 24, 2026
be28abf
Release 0.1.5.4
sethforprivacy Aug 24, 2026
f5f0d4c
Merge pull request #36 from sethforprivacy/release/v0.1.5.4
sethforprivacy Aug 24, 2026
2d8ae66
Route every settled BOLT11 to its BTCPay invoice, surviving restarts
sethforprivacy Aug 25, 2026
edfdf1e
Release 0.1.5.5
sethforprivacy Aug 25, 2026
63b9808
Merge pull request #38 from sethforprivacy/flint-superseded-invoice-r…
sethforprivacy Aug 25, 2026
496f3a5
Merge pull request #39 from sethforprivacy/release/v0.1.5.5
sethforprivacy Aug 25, 2026
0c5e89b
Keep the mint-time hash→invoice association independent of LUD-21
sethforprivacy Aug 26, 2026
4a17864
Fix raw SQL insert in the payment-hash index
sethforprivacy Aug 26, 2026
36451d5
[ci] retrigger checks on the fixed SHA
sethforprivacy Aug 26, 2026
c47bce2
Bump Breez.Sdk.Spark from 0.22.3 to 0.23.0
sethforprivacy Aug 26, 2026
4f86be3
Merge pull request #41 from sethforprivacy/flint-breez-0.23.0
sethforprivacy Aug 26, 2026
0794d7b
Release 1.0.0
sethforprivacy Aug 26, 2026
6716a67
Merge pull request #44 from sethforprivacy/release/v1.0.0
sethforprivacy Aug 26, 2026
27cf667
Warn non-admin tenants that the Spark seed is readable by the server …
sethforprivacy Aug 26, 2026
ec64c13
Merge pull request #45 from sethforprivacy/flint-tenant-custody-warning
sethforprivacy Aug 26, 2026
112fe5c
Release 1.0.1
sethforprivacy Aug 26, 2026
eb2c6f1
Merge pull request #46 from sethforprivacy/release/v1.0.1
sethforprivacy Aug 26, 2026
d3a6831
Unwrap mid-sentence line breaks in the release notes template
sethforprivacy Aug 26, 2026
493713f
Merge pull request #47 from sethforprivacy/flint-release-notes-wrapping
sethforprivacy Aug 26, 2026
7966ed6
Strip debug info from the packaged native payload (~100 MB smaller)
sethforprivacy Aug 27, 2026
314a053
Share one Spark payment-history scan across a reconciliation page
sethforprivacy Aug 27, 2026
b0b80a8
Read the process-global Spark network status once, not once per store
sethforprivacy Aug 27, 2026
b219191
Skip scrubbing for SDK log lines below the effective level
sethforprivacy Aug 27, 2026
a02b3db
Record the packaging and performance changes in the changelog
sethforprivacy Aug 27, 2026
fcfc021
Pin the docker fallback image by digest; it strips shipped bytes
sethforprivacy Aug 27, 2026
5e715e0
Merge pull request #48 from sethforprivacy/flint-strip-and-sweep
sethforprivacy Aug 27, 2026
047b4f1
Release 1.0.2
sethforprivacy Aug 27, 2026
e3ca95e
Merge pull request #49 from sethforprivacy/release/v1.0.2
sethforprivacy Aug 27, 2026
3923ca5
Pin every GitHub Action by commit SHA
sethforprivacy Aug 28, 2026
94362b5
Pin the CI Postgres image and the .NET SDK
sethforprivacy Aug 28, 2026
70d894a
Strip the osx native payload everywhere, in the pinned container
sethforprivacy Aug 28, 2026
f0784a0
Pin SSH.NET to 2026.0.0 in the plugin
sethforprivacy Aug 28, 2026
831ed3b
Add a partial index for the credit sweep
sethforprivacy Aug 28, 2026
05bb715
Record the audit changes in the changelog and release docs
sethforprivacy Aug 28, 2026
2cfbe34
Keep the SSH.NET pin out of the shipped artifact
sethforprivacy Aug 28, 2026
c3275f4
Release 1.0.3
sethforprivacy Aug 28, 2026
24d71a8
Merge pull request #51 from sethforprivacy/flint-audit-strip-and-pins
sethforprivacy Aug 28, 2026
b435a4c
Re-apply the original file mode after replacing a stripped dylib
sethforprivacy Aug 28, 2026
9530a4a
Anchor the SHA256SUMS digest strip to the hex prefix
sethforprivacy Aug 28, 2026
2f6bc8d
Merge pull request #52 from sethforprivacy/fix/strip-mode-rename
sethforprivacy Aug 28, 2026
6926ee6
Extend funded-regtest audit withholding to preimage and session-token…
sethforprivacy Aug 31, 2026
f3552c6
Merge pull request #55 from sethforprivacy/security/hardening-2026-08-31
sethforprivacy Sep 1, 2026
2ec85c3
Add a partial covering index for the settleable invoice walk
sethforprivacy Sep 1, 2026
1cc7969
Scrub merchant-facing error text at the SparkErrors.Describe choke point
sethforprivacy Sep 1, 2026
5cc5be0
Keep the storage path out of the lock refusal a store manager is shown
sethforprivacy Sep 1, 2026
1e45ce9
Release the storage lock when a store's Spark connect throws
sethforprivacy Sep 1, 2026
a1425b8
Gate forwarded.log through the funded-audit secret check before writi…
sethforprivacy Sep 1, 2026
7823e2a
Pin NuGet resolution with committed lock files and a locked-mode CI r…
sethforprivacy Sep 1, 2026
711a708
Pass the packaged-notices check its values through python argv
sethforprivacy Sep 1, 2026
39dc793
Refuse caching on every Spark page so a rejected mnemonic is never st…
sethforprivacy Sep 1, 2026
cf0246b
Forbid redirect following on the cross-chain catalogue client
sethforprivacy Sep 1, 2026
eb9b412
Truncate InvoicePaymentHashes between Postgres suites too
sethforprivacy Sep 1, 2026
855f4f5
Strip in the docker Mach-O fallback, prune win-x86, and emit dev sett…
sethforprivacy Sep 1, 2026
6e78a25
Resolve the setup-tab store from the request authorisation, not the f…
sethforprivacy Sep 2, 2026
03f10d3
Document the render-time authorised-store match in the trust model
sethforprivacy Sep 2, 2026
5aee66f
Order the settleable-invoice walk by expiry so the partial index is used
sethforprivacy Sep 2, 2026
4ca99e0
Dispose the unadopted SDK handle and complete its event channel on a …
sethforprivacy Sep 2, 2026
3b3b55d
Correct the win-x86 docs, harden the scrub fallback and jq guard, and…
sethforprivacy Sep 2, 2026
956c9dd
Print preimage fingerprints unconditionally and leave withheld marker…
sethforprivacy Sep 2, 2026
76cc109
Drop the dead INCLUDE payload from the settleable invoice index
sethforprivacy Sep 2, 2026
02878de
Retitle the walk restarts as soonest-expiring and note the short-TTL …
sethforprivacy Sep 2, 2026
da4f3f7
Pin the planner's use of the settleable partial index with a Postgres…
sethforprivacy Sep 2, 2026
a68b271
Make the Breez SDK check and bump patterns survive the bracketed exac…
sethforprivacy Sep 2, 2026
d3d44a6
Condition the lock-file property off for the migration build and docu…
sethforprivacy Sep 2, 2026
1381b40
Skip the implicit restore after locked-mode restores and drop prefix …
sethforprivacy Sep 2, 2026
c88bbf5
Restrict every package id to api.nuget.org with a packageSourceMapping
sethforprivacy Sep 2, 2026
59c458c
Gate payment-hash prompt recording on any Flint store being provisioned
sethforprivacy Sep 2, 2026
3196f82
Add 14-day retention with a FirstSeenAt index for the payment-hash as…
sethforprivacy Sep 2, 2026
f30c37b
Bound the indexer gate's startup-gate wait and correct the retention …
sethforprivacy Sep 2, 2026
85d2113
Drop the settleable index from the retention migration's designer now…
sethforprivacy Sep 2, 2026
145a7a2
Resolve the setup partials from the authorised store alone and pin bo…
sethforprivacy Sep 2, 2026
03cb684
Merge pull request #56 from sethforprivacy/security/s1-authorised-store
sethforprivacy Sep 2, 2026
830c055
Merge pull request #57 from sethforprivacy/fix/spark-connect-throw-st…
sethforprivacy Sep 2, 2026
a738438
Merge pull request #63 from sethforprivacy/hardening/cheap-lows
sethforprivacy Sep 2, 2026
8727264
Merge pull request #58 from sethforprivacy/fix/audit-artifact-gating
sethforprivacy Sep 2, 2026
125b7c4
Merge pull request #59 from sethforprivacy/build/nuget-locking
sethforprivacy Sep 2, 2026
fe8ccd8
Merge pull request #61 from sethforprivacy/perf/settleable-invoice-index
sethforprivacy Sep 2, 2026
8aa09f4
Merge pull request #62 from sethforprivacy/perf/payment-hash-indexer-…
sethforprivacy Sep 2, 2026
0056615
Classify the cross-store Lightning sweep from loaded stores and run i…
sethforprivacy Sep 1, 2026
50ef286
Merge pull request #60 from sethforprivacy/perf/config-sweep-n-plus-one
sethforprivacy Sep 2, 2026
c15dc8e
Release 1.0.4
sethforprivacy Sep 2, 2026
e0a31e3
Merge pull request #64 from sethforprivacy/release/v1.0.4
sethforprivacy Sep 2, 2026
dc83ffe
Bump btcpayserver submodule to v2.4.4
sethforprivacy Sep 7, 2026
aeb3425
Enforce Breez.Sdk.Spark release gating past the Dependabot ignore
sethforprivacy Sep 7, 2026
c2c12ff
Merge pull request #66 from sethforprivacy/chore/btcpayserver-v2.4.4
sethforprivacy Sep 7, 2026
788cd37
Merge pull request #67 from sethforprivacy/ci/breez-release-gating
sethforprivacy Sep 7, 2026
95fa4fc
Release 1.1.0
sethforprivacy Sep 7, 2026
01f80a4
Merge pull request #69 from sethforprivacy/release/v1.1.0
sethforprivacy Sep 7, 2026
c63e9e9
Add a local Spark regtest e2e suite backed by cashu-regtest and open-ssp
sethforprivacy Sep 8, 2026
24d3c85
Gate releases on the local Spark stack, prebuild its images, add a BT…
sethforprivacy Sep 8, 2026
e8e0c62
Keep the NuGet cache post-step from walking the fixture's root-owned …
sethforprivacy Sep 8, 2026
5365332
Merge pull request #71 from sethforprivacy/claude/flint-e2e-stage2-re…
sethforprivacy Sep 8, 2026
3d7dab3
Point the image-publish bake at the fixture checkout, not this repo's…
sethforprivacy Sep 8, 2026
73b3d55
Merge pull request #73 from sethforprivacy/ci/images-bake-local-source
sethforprivacy Sep 8, 2026
4bbb7e5
Give bake-action the fixture checkout as its working directory
sethforprivacy Sep 8, 2026
e62d010
Merge pull request #74 from sethforprivacy/ci/images-bake-source-dir
sethforprivacy Sep 8, 2026
187bbc5
Pass bake-action a comma-separated target list
sethforprivacy Sep 8, 2026
e739bce
Merge pull request #75 from sethforprivacy/ci/images-bake-targets-list
sethforprivacy Sep 8, 2026
c76e470
Restore the NuGet cache without a post-save step in local-regtest
sethforprivacy Sep 8, 2026
5ce0ee9
Merge pull request #76 from sethforprivacy/ci/local-regtest-cache-res…
sethforprivacy Sep 8, 2026
8faa77f
Merge pull request #19 from sethforprivacy/unilateral-exit
sethforprivacy Sep 14, 2026
fc1f668
Bump Breez.Sdk.Spark to 0.25.0 and rework the exit seam for the new API
sethforprivacy Sep 14, 2026
9101908
Rework the unilateral exit for the Breez SDK 0.25 flow: check-in, sta…
sethforprivacy Sep 15, 2026
0598df4
Ground the CheckAsync leaf placeholder in the SDK's documented contract
sethforprivacy Sep 15, 2026
fe344cc
Import the exit-state backup when the wallet starts
sethforprivacy Sep 15, 2026
7b8254f
Say where a failed exit-state import shows up
sethforprivacy Sep 15, 2026
0e47ea4
Import the exit-state backup before the wallet's first sync, as docum…
sethforprivacy Sep 15, 2026
1f6ddfb
Keep the lock files' transitive pins at what main resolves
sethforprivacy Sep 15, 2026
fc1eb4a
Guard the nullable claim payment the 0.25 binding introduced
sethforprivacy Sep 15, 2026
f4547ed
Test a unilateral exit end to end against the local Spark stack
sethforprivacy Sep 15, 2026
df59e65
Regenerate both lock files against the pinned btcpayserver, not the l…
sethforprivacy Sep 15, 2026
7b97fed
Document what the end-to-end exit test costs the fixture
sethforprivacy Sep 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@
version: 2

updates:
# Breez.Sdk.Spark and any other NuGet packages referenced directly by the plugin project.
# Pre-1.0 and ships frequent releases, some of them explicit prereleases (e.g. "0.20.0-dev1")
# — this repo pins stable only (see the comment on the PackageReference in the .csproj).
# No explicit `ignore` rule for that is configured: dependabot.yml's
# `ignore.update-types` only supports semver-major/minor/patch, not a "prerelease" type, and
# Dependabot's own default behaviour already only proposes stable-to-stable updates when the
# pinned version (0.19.2 here) isn't itself a prerelease — confirmed against community reports
# of the opposite problem (dependabot/feedback#451: prerelease-pinned projects not being
# offered further prereleases), not against a live run of this repo. Watch the first PR
# Dependabot opens here to confirm it holds; if it ever proposes a prerelease, an explicit
# `ignore: - dependency-name: "Breez.Sdk.Spark", versions: ["*-*"]`-style pattern would be the
# fallback (NuGet ignore version patterns are glob-style, not semver ranges).
# NuGet packages referenced directly by the plugin project — except Breez.Sdk.Spark, ignored
# below: Breez tags and pushes patch versions to NuGet with no GitHub Release and no notes
# (0.22.1 through 0.22.3 all shipped that way), and a Dependabot PR per push is churn, not
# signal. .github/workflows/breez-sdk-update.yml is the release-aware replacement — proposing a
# bump only for versions upstream has published a release for. A tag-only fix worth shipping
# early is bumped by hand.
#
# That split once failed silently in the other direction: the ignore below worked while the pin
# was a plain version (no bump proposed between 2026-08-22 and 2026-09-02), and stopped working
# as soon as the pin became a bracketed exact-version range (7823e2a changed it on 2026-09-02;
# Dependabot proposed a PR for tag-only 0.24.1 on 2026-09-03, PR #65). Two countermeasures
# since: `versions: ["*"]` re-routes the ignore through the version-pattern matcher, and
# .github/workflows/breez-dependabot-guard.yml closes any Dependabot PR that still names
# Breez.Sdk.Spark, so a Dependabot quirk can open nothing but noise that dies without a human.
#
# Also note: Dependabot's nuget updater resolves the project's ProjectReference to
# ../btcpayserver/BTCPayServer/BTCPayServer.csproj, which lives in a git submodule; this is
Expand All @@ -32,6 +34,12 @@ updates:
open-pull-requests-limit: 5
commit-message:
prefix: "chore(deps)"
ignore:
# The versions condition is not a statement that some versions may be proposed: it matches
# every version, on the strength of the incident described above — make the ignore survive
# whatever format the PackageReference pin takes next.
- dependency-name: "Breez.Sdk.Spark"
versions: ["*"]

# Test-project NuGet packages -- xunit.v3, and since the move to Microsoft.Testing.Platform that is the
# whole list; the VSTest host and adapter it used to name here are gone. Separate entry because
Expand Down
10 changes: 4 additions & 6 deletions .github/release-notes-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ writes it with a single space between hash and filename. GNU `sha256sum -c` acce

## Installing

**Server settings → Plugins → Upload plugin**, and select `BTCPayServer.Plugins.Flint.btcpay`.
BTCPay restarts itself to finish. Requires BTCPay Server 2.4.1 or newer, on a non-Alpine host.
**Server settings → Plugins**, find **Flint** in the plugin store ([official listing](https://plugin-builder.btcpayserver.org/public/plugins/flint)), and install it. BTCPay restarts itself to finish.

Read [CHANGELOG.md](https://github.com/__REPO__/blob/__TAG__/CHANGELOG.md) for what is in this
release and how far it has actually been proven, and the
[trust model](https://github.com/__REPO__/blob/__TAG__/docs/trust-model.md), before you put money
through it.
Alternatively, **Server settings → Plugins → Upload plugin**, and select `BTCPayServer.Plugins.Flint.btcpay`. BTCPay restarts itself to finish. Both routes require BTCPay Server 2.4.1 or newer, on a non-Alpine host.

Read the [CHANGELOG](https://github.com/__REPO__/blob/__TAG__/CHANGELOG.md) for what is in this release and how far it has actually been proven, and the [trust model](https://github.com/__REPO__/blob/__TAG__/docs/trust-model.md), before you put money through it.
55 changes: 55 additions & 0 deletions .github/workflows/breez-dependabot-guard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Breez Dependabot guard

# Dependabot's NuGet ignore rules are not a reliable gate: the name-only ignore for
# Breez.Sdk.Spark held while the pin was a plain version, and silently stopped working the day
# the pin became a bracketed exact range (7823e2a, 2026-09-02) — Dependabot proposed a PR for
# tag-only 0.24.1 the next morning (PR #65, 2026-09-03), defeating the policy that Breez bumps
# arrive only from .github/workflows/breez-sdk-update.yml, which proposes a version only when
# upstream has a *published GitHub Release* for it (see the comment on that workflow and on
# dependabot.yml for why tag-only bumps are deliberate churn).
#
# This workflow enforces that policy at the PR layer instead of trusting the ignore: any PR
# authored by Dependabot that names Breez.Sdk.Spark is closed and its branch deleted. Human
# PRs (including hand-applied tag-only bumps) are untouched: the guard fires only for
# dependabot[bot]. If a Dependabot quirk resurrects a PR, this closes it without a human ever
# having to look at it.

on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:

permissions: {}

jobs:
guard:
name: Close Dependabot Breez.Sdk.Spark PR
# Fails closed: a PR not authored by dependabot[bot], or already deleted before this job
# runs, is a no-op, not an error.
if: >-
github.actor == 'dependabot[bot]' &&
contains(github.event.pull_request.title, 'Breez.Sdk.Spark')
runs-on: ubuntu-latest
permissions:
# Deleting the guarded PR's branch needs contents; closing + commenting needs PRs.
contents: write
pull-requests: write
steps:
# No checkout needed: gh acts on the PR number directly.
- name: Close the PR and delete its branch
env:
GH_TOKEN: ${{ github.token }}
PR: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
comment="$(cat <<BODY
Closed automatically by \`.github/workflows/breez-dependabot-guard.yml\`.

Dependabot's ignore for \`Breez.Sdk.Spark\` has a documented hole when the PackageReference
pin changes format (name-only ignore defeated by an exact-version bracket), so Breez bump
PRs must arrive only from \`.github/workflows/breez-sdk-update.yml\`, which proposes a
version only when upstream has a published GitHub Release for it. A tag-only fix worth
shipping early is bumped by hand.
BODY
)"
gh pr close "$PR" --comment "$comment" --delete-branch --repo "$GITHUB_REPOSITORY"
156 changes: 156 additions & 0 deletions .github/workflows/breez-sdk-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
name: Breez SDK update

# Dependabot's nuget ecosystem proposes a PR for every Breez.Sdk.Spark version pushed to NuGet,
# and Breez tags and pushes patch versions with no GitHub Release and no notes (0.22.1 through
# 0.22.3 all shipped that way) — a PR per push is churn, not signal. This workflow is the
# release-aware equivalent, mirroring btcpayserver-update.yml for the same reason that one
# replaced Dependabot's gitsubmodule ecosystem: weekly plus on-demand, it looks for the newest
# version breez/spark-sdk has a *published GitHub Release* for (that also exists on NuGet, so
# the PR can restore), and opens a bump PR only then. Breez.Sdk.Spark is ignored in
# dependabot.yml so the two do not both propose bumps; because that ignore proved leaky once the
# pin format changed (see breez-dependabot-guard.yml), a guard workflow also closes any
# Dependabot PR that names Breez.Sdk.Spark — the release gate is enforced, not assumed.
# A tag-only fix worth shipping early is a
# human decision: bump the PackageReference by hand, exactly as 0.22.2 and 0.22.3 were.
#
# Token: default GITHUB_TOKEN, with the same workflow_dispatch re-dispatch trick as
# btcpayserver-update.yml so ci.yml actually runs on the PR this opens (GITHUB_TOKEN-authored
# pushes do not fire pull_request workflows; workflow_dispatch is exempt from that rule).

on:
schedule:
- cron: "0 6 * * 2" # Tuesdays 06:00 UTC — offset from the Monday btcpayserver check
workflow_dispatch:
inputs:
dry_run:
description: "Detect only: print the result and diff, but do not push or open a PR"
type: boolean
default: false

permissions:
contents: write
pull-requests: write
actions: write # to re-dispatch ci.yml on the bump branch, see above

jobs:
check:
name: Check for a newer Breez SDK release
runs-on: ubuntu-latest
# Discovery only reads the csproj and talks to the NuGet/GitHub APIs: the
# write powers the bump job needs must not leak into the scheduled check.
permissions:
contents: read
outputs:
changed: ${{ steps.check.outputs.changed }}
current: ${{ steps.check.outputs.current }}
latest: ${{ steps.check.outputs.latest }}
release_url: ${{ steps.check.outputs.release_url }}
steps:
# No submodule checkout needed: the discovery script only reads the csproj and queries the
# GitHub and NuGet APIs, so this stays cheap enough to run unconditionally every week.
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Run discovery script
id: check
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
out="$(scripts/check-breez-sdk-update.sh)"
echo "Discovery result: $out"
{
echo "changed=$(jq -r .changed <<<"$out")"
echo "current=$(jq -r .current <<<"$out")"
echo "latest=$(jq -r .latest <<<"$out")"
echo "release_url=$(jq -r .release_url <<<"$out")"
} >> "$GITHUB_OUTPUT"

bump:
name: Open bump PR
needs: check
if: ${{ needs.check.outputs.changed == 'true' }}
runs-on: ubuntu-latest
env:
CURRENT: ${{ needs.check.outputs.current }}
LATEST: ${{ needs.check.outputs.latest }}
RELEASE_URL: ${{ needs.check.outputs.release_url }}
DRY_RUN: ${{ github.event.inputs.dry_run }}
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Configure git identity
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Bump Breez.Sdk.Spark to ${{ needs.check.outputs.latest }}
run: |
set -euo pipefail
# The pin is an exact-version bracket pin (Version="[0.25.0]"): the sed keeps the
# brackets on the way out, and \[?[0-9][0-9.]*\]? also survives a future unbracketed
# pin. The guard greps fixed-string, since a literal "[0.24.0]" would otherwise be a
# character class to grep.
sed -i -E \
"s|(<PackageReference Include=\"Breez.Sdk.Spark\" Version=\")\[?[0-9][0-9.]*\]?(\")|\1[$LATEST]\2|" \
BTCPayServer.Plugins.Flint/BTCPayServer.Plugins.Flint.csproj
if ! grep -qF "Include=\"Breez.Sdk.Spark\" Version=\"[$LATEST]\"" \
BTCPayServer.Plugins.Flint/BTCPayServer.Plugins.Flint.csproj; then
echo "error: the PackageReference did not end up at [$LATEST]; refusing to open a PR" >&2
exit 1
fi
git add BTCPayServer.Plugins.Flint/BTCPayServer.Plugins.Flint.csproj
git status --short

- name: Create branch and commit
id: commit
run: |
set -euo pipefail
branch="chore/breez-sdk-$LATEST"
echo "branch=$branch" >> "$GITHUB_OUTPUT"

if [ "$DRY_RUN" = "true" ]; then
echo "DRY RUN — diff only, not pushing:"
git --no-pager diff --cached
exit 0
fi

git switch -c "$branch"
git commit -m "Bump Breez.Sdk.Spark to $LATEST"
git push -f origin "$branch"

- name: Open or update PR
if: ${{ github.event.inputs.dry_run != 'true' }}
env:
GH_TOKEN: ${{ github.token }}
BRANCH: ${{ steps.commit.outputs.branch }}
run: |
set -euo pipefail
title="Bump Breez.Sdk.Spark: $CURRENT -> $LATEST"
body="$(cat <<BODY
Bumps \`Breez.Sdk.Spark\` from \`$CURRENT\` to \`$LATEST\`, a version upstream has published
a GitHub Release for — tag-only NuGet pushes are deliberately not proposed (see
\`.github/workflows/breez-sdk-update.yml\`).

Upstream release notes: $RELEASE_URL

The SDK is pre-1.0 with no stability promise between releases: read the notes (when they
exist) and the API-surface diff before merging, per the pinning comment on the
PackageReference. CI on this PR — including the live and funded regtest suites — is the
merge gate, not a substitute for that read.
BODY
)"

open_count="$(gh pr list --head "$BRANCH" --state open --json number --jq 'length')"
if [ "$open_count" = "0" ]; then
gh pr create --base main --head "$BRANCH" --title "$title" --body "$body"
echo "Opened PR for $BRANCH."
else
gh pr edit "$BRANCH" --title "$title" --body "$body"
echo "PR already open for $BRANCH; force-pushed branch updated it."
fi

# See the workflow-level comment: workflow_dispatch is exempt from GITHUB_TOKEN's
# loop-prevention rule, so this is what actually gets ci.yml to run on the PR.
gh workflow run ci.yml --ref "$BRANCH"
32 changes: 29 additions & 3 deletions .github/workflows/btcpayserver-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ jobs:
check:
name: Check for a newer stable btcpayserver release
runs-on: ubuntu-latest
# Discovery only reads Constants.cs and runs git ls-remote: the write
# powers the bump job needs must not leak into the scheduled check.
permissions:
contents: read
outputs:
changed: ${{ steps.check.outputs.changed }}
current: ${{ steps.check.outputs.current }}
Expand All @@ -47,7 +51,7 @@ jobs:
# repo and queries the upstream remote's tag list over the network (git ls-remote), so this
# stays cheap enough to run unconditionally every week.
- name: Check out repository
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Run discovery script
id: check
Expand All @@ -74,10 +78,20 @@ jobs:
DRY_RUN: ${{ github.event.inputs.dry_run }}
steps:
- name: Check out repository
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

# Lock regeneration needs the .NET SDK: the submodule bump changes the ProjectReference
# version constraints (btcpayserver's Build/Version.csproj carries the release number), and
# the committed packages.lock.json files must be regenerated to match. Without this step the
# bump PR fails CI at "Restore (locked mode)" with NU1004, as seen on chore/btcpayserver-v2.4.3
# (run 184, 2026-09-07) — the bump step edited the submodule but never the locks.
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
dotnet-version: "10.0.x"

- name: Configure git identity
run: |
git config user.name "github-actions[bot]"
Expand All @@ -101,7 +115,19 @@ jobs:
BTCPayServer.Plugins.Flint/Constants.cs
sed -i -E "s/\`v[0-9]+\.[0-9]+\.[0-9]+\`\)\./\`v$LATEST\`)./" docs/building.md

git add btcpayserver BTCPayServer.Plugins.Flint/Constants.cs docs/building.md
# Regenerate the committed lock files against the bumped graph, then prove they agree
# with it under locked mode — the same property CI's "Restore (locked mode)" checks on
# the PR, so a lock that drifts from the csprojs fails here at the bump step, before a
# PR anyone has to review even exists. Unlocked restore rewrites them in place; locked
# re-restore must then be a no-op.
dotnet restore BTCPayServer.Plugins.Flint/BTCPayServer.Plugins.Flint.csproj
dotnet restore BTCPayServer.Plugins.Flint.Tests/BTCPayServer.Plugins.Flint.Tests.csproj
dotnet restore --locked-mode BTCPayServer.Plugins.Flint/BTCPayServer.Plugins.Flint.csproj
dotnet restore --locked-mode BTCPayServer.Plugins.Flint.Tests/BTCPayServer.Plugins.Flint.Tests.csproj

git add btcpayserver BTCPayServer.Plugins.Flint/Constants.cs docs/building.md \
BTCPayServer.Plugins.Flint/packages.lock.json \
BTCPayServer.Plugins.Flint.Tests/packages.lock.json
git status --short

- name: Create branch and commit
Expand Down
Loading
Loading