Merged
Conversation
- Add optional sendPayment(bolt11) to LightningBackend for outbound payments (session refunds). Implemented in all 5 backends: Phoenixd, LND, CLN, LNbits, NWC. - Add SessionConfig type and ietfSession config to BoothConfig. - Add sessions table to SQLite storage with migration, indexes, and atomic deduct/topUp transactions. - Add session methods to StorageBackend interface and both SQLite and memory implementations. - 826 tests pass, zero regressions.
- satgate repo is TheCryptoDonkey/satgate, not forgesworn/satgate - blog post: update year (25 -> 27) and replace dead routing.trotters.cc with current live demos (jokes.trotters.dev, satgate.trotters.dev)
- New createIETFSessionRail() factory implementing deposit/bearer/ top-up/close lifecycle per forgesworn/payment-methods session spec. - Compliance guardrails: maxSessionDurationMs (24h default), maxDepositSats (100k default), auto-close sweep for expired sessions, refund-to-originator enforcement. - Session events: open, close, expire, topup, deduct callbacks. - Bearer token auth for subsequent requests after session open. - 18 new tests covering full lifecycle, compliance caps, security (HMAC tamper, invalid preimage, unknown bearer, token uniqueness). - COMPLIANCE.md documenting regulatory posture, data handling, custody considerations, and operator responsibilities. - Public API exports in index.ts. - 844 tests pass, zero regressions.
CRITICAL fixes: - Remove close-time return invoice override — refund-to-originator enforcement prevents refund redirect attacks. - Add BOLT11 amount validation before refund payment — prevents operator fund drain from amount-mismatched return invoices. HIGH fixes: - TOCTOU double-refund: close session before attempting payment in sweepExpired, preventing concurrent close + sweep double-spend. - LND streaming JSON parse: wrap in try/catch per line to handle malformed/truncated responses gracefully. - sweepExpired: emit events on failure for operator visibility. MEDIUM fixes: - Session open replay: check for existing session before creating, preventing memory storage overwrite and SQLite unhandled throw. - Fail-fast at rail construction if backend lacks sendPayment().
- Add 'session' mode to RailVerifyResult for session bearer auth. - Engine uses storage.deductSession() for session-mode requests instead of credits table debit. - Session-specific response headers: X-Session-Balance, Cache-Control private/no-store. - Auth hint for session rail in 402 challenge bodies. - Public API exports for session rail and types. - 844 tests pass, zero regressions.
Security fixes: - Bearer token timing-safe comparison in memory storage (timingSafeEqual) - NWC sendPayment timeout via Promise.race (prevents hanging sweep) - Top-up cap now uses cumulative depositSats, not current balanceSats New adversarial tests (8): - Duplicate session open (replay prevention) - Expired challenge rejection - Bearer auth on expired session - Close replay on already-closed session - Missing returnInvoice graceful handling - sendPayment failure during close (session still closes) - Malformed base64url in Authorization header - Top-up with fresh challenge succeeds 852 tests pass, zero regressions.
github-actions bot
pushed a commit
that referenced
this pull request
Mar 24, 2026
# [4.4.0](v4.3.0...v4.4.0) (2026-03-24) ### Bug Fixes * address security audit findings (CRITICAL + HIGH + MEDIUM) ([bc94c21](bc94c21)) * remaining MEDIUM security fixes + adversarial test coverage ([c45792e](c45792e)) ### Features * add IETF Payment session rail with compliance guardrails ([73f3597](73f3597)) * add PaymentSender interface and session storage ([e1fa026](e1fa026)) * IETF Payment session intent ([#5](#5)) ([8d770fa](8d770fa)) * integrate session rail into TollBoothEngine ([ab65a6d](ab65a6d))
|
🎉 This PR is included in version 4.4.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
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.
Summary
Implements the IETF Payment session intent (deposit/bearer/top-up/close lifecycle) per the
forgesworn/payment-methodssession specification. This enables streaming payment sessions for use cases like LLM token streaming, ridesharing metering, and real-time data feeds.5 commits:
sendPayment(bolt11)on all 5 Lightning backends (Phoenixd, LND, CLN, LNbits, NWC) for outbound refund paymentscreateIETFSessionRail()factory with full lifecycle (challenge, open, bearer, top-up, close)'session'mode in TollBoothEngine,deductSession,X-Session-Balanceheaders,Cache-Control: private, no-storeCompliance guardrails built in:
maxSessionDurationMs(default 24h) — prevents indefinite custodymaxDepositSats(default 100k sats) — limits value heldNew files:
src/core/ietf-session.ts— session rail implementationsrc/core/ietf-session.test.ts— 26 tests (lifecycle, compliance, security, adversarial)COMPLIANCE.md— regulatory posture documentationTest plan
🤖 Generated with Claude Code