x402-rack 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,304 @@
1
+ # Architecture: The Rack Stack for BSV HTTP Services
2
+
3
+ ## Overview
4
+
5
+ HTTP services monetised with BSV require several orthogonal concerns to be handled: identity, payment, fee sponsorship, and settlement. These concerns compose naturally as a Rack middleware stack, where each layer handles one responsibility and passes context downstream.
6
+
7
+ This plan defines the component parts and their boundaries. It is deliberately not concerned with implementation specifics — it maps the jigsaw pieces and how they fit together.
8
+
9
+ ## The Stack
10
+
11
+ ```
12
+ ┌─────────────────────────────────────────────┐
13
+ │ TLS (transport security) │ Not our concern — handled by web server
14
+ ├─────────────────────────────────────────────┤
15
+ │ BRC-104 Auth Middleware (optional) │ Identity — who is this?
16
+ ├─────────────────────────────────────────────┤
17
+ │ X402 Middleware (gatekeeper) │ Payment gating — have they paid?
18
+ ├─────────────────────────────────────────────┤
19
+ │ Application │ Business logic — serve the resource
20
+ └─────────────────────────────────────────────┘
21
+
22
+ ┌──────────────┐
23
+ │ Gateways │ Settlement — how do they pay?
24
+ └──────┬───────┘
25
+
26
+ ┌───────────┼───────────┐
27
+ │ │ │
28
+ ┌───┴────┐ ┌───┴────┐ ┌────┴────┐
29
+ │ BSV │ │ BSV │ │ BRC-105 │ ... extensible
30
+ │ Proof │ │ Pay │ │ Gateway │
31
+ └───┬────┘ └───┬────┘ └────┬────┘
32
+ │ │ │
33
+ └───────────┼───────────┘
34
+
35
+ ┌──────┴───────┐
36
+ │ BSV Wallet │ Server-side wallet (BRC-100 interface)
37
+ │ (bsv-wallet │ Manages keys, UTXOs, signing
38
+ │ gem) │ via baskets: nonces, fees, revenue
39
+ └──────┬───────┘
40
+
41
+ ┌──────┴───────┐
42
+ │ bsv-sdk │ Primitives — keys, txs, scripts, ARC
43
+ └──────────────┘
44
+ ```
45
+
46
+ ## Layer 1: Identity (BRC-103/104)
47
+
48
+ **What**: Mutual authentication between client and server. Establishes who is making the request.
49
+
50
+ **Rack middleware**: Verifies `x-bsv-auth-*` headers, validates BRC-103 signatures over the request (method, path, query, whitelisted headers, body). Places the authenticated identity into the Rack env.
51
+
52
+ **Provides to downstream**: `env['brc103.identity_key']` (33-byte compressed public key), session nonces, certificate data.
53
+
54
+ **Optional**: Not all payment flows require identity. Anonymous payments (merkleworks x402, BSV-pay) work without this layer. BRC-105 payments require it.
55
+
56
+ **Not our gem**: This would be a separate gem (`brc104-rack` or similar). Our x402 middleware doesn't depend on it — it just benefits from it when present.
57
+
58
+ ## Layer 2: Payment Gating (X402 Middleware)
59
+
60
+ **What**: The gatekeeper. Decides whether a request should be served based on payment status.
61
+
62
+ **Responsibilities**:
63
+ - Route matching — is this request to a protected endpoint?
64
+ - Challenge issuance — poll gateways, return 402 with challenge headers
65
+ - Proof dispatch — detect which proof header arrived, dispatch to the matching gateway
66
+ - Access control — gateway says allow/deny, middleware serves or rejects
67
+
68
+ **Does NOT do**:
69
+ - Sign transactions
70
+ - Hold private keys
71
+ - Decode blockchain data
72
+ - Talk to ARC or any network service
73
+ - Know what chain or protocol is being used
74
+
75
+ **Rack env it reads**: route configuration, gateway list. Optionally `env['brc103.identity_key']` (passes through to gateways that need it).
76
+
77
+ **Rack env it sets**: settlement result (for downstream logging/receipt headers).
78
+
79
+ **This is our gem**: `x402-rack`.
80
+
81
+ ## Layer 3: Settlement (Gateways)
82
+
83
+ **What**: The bridge between HTTP and blockchain. Each gateway knows one settlement protocol.
84
+
85
+ **Responsibilities**:
86
+ - Build challenge data (headers + partial tx templates)
87
+ - Verify and settle proofs/payments
88
+ - Interact with external services (ARC, treasury, wallets)
89
+ - Can hold keys and sign transactions
90
+
91
+ **Gateway types identified so far**:
92
+
93
+ ### BSV PayGateway (our BSV-native scheme — Coinbase v2 headers)
94
+ - **Challenge**: `PaymentRequired` JSON with BSV in `accepts` array + partial tx template (payment output only)
95
+ - **Settlement**: verify tx structure, broadcast via ARC, return `Payment-Response`
96
+ - **Headers**: `Payment-Required` / `Payment-Signature` / `Payment-Response`
97
+ - **Needs**: ARC only
98
+ - **Identity**: not required
99
+ - **Ecosystem**: standard x402 v2 — interoperable with any Coinbase-compatible client
100
+
101
+ ### BSV ProofGateway (merkleworks x402)
102
+ - **Challenge**: pre-signed partial tx template (nonce at input 0 with 0xC3, payment output at output 0) + merkleworks challenge JSON (binding, expiry)
103
+ - **Settlement**: verify tx structure, check mempool via ARC
104
+ - **Headers**: `X402-Challenge` / `X402-Proof`
105
+ - **Needs**: treasury (nonce key) + ARC
106
+ - **Identity**: not required
107
+ - **Ecosystem**: merkleworks BSV-specific
108
+
109
+ ### BRC-105 Gateway (future)
110
+ - **Challenge**: derivation prefix + satoshis required (multiple `x-bsv-payment-*` headers)
111
+ - **Settlement**: verify derivation, validate tx via BRC-100 wallet (`internalizeAction`)
112
+ - **Headers**: `x-bsv-payment-*` / `x-bsv-payment`
113
+ - **Needs**: BRC-100 wallet
114
+ - **Identity**: REQUIRED (reads `env['brc103.identity_key']` for derivation)
115
+ - **Ecosystem**: BSV Association BRC standard
116
+
117
+ ## Server-Side Wallet (`bsv-wallet` gem)
118
+
119
+ ### One wallet, multiple roles
120
+
121
+ The treasury, delegator, and payment receipt functions are not separate services — they are **roles** a single wallet plays, distinguished by which baskets and keys they use.
122
+
123
+ | Role | Basket | Key | Operations |
124
+ |------|--------|-----|------------|
125
+ | Treasury | `x402-nonces` | Nonce key | `createAction` (mint nonces, sign templates), `listOutputs` |
126
+ | Delegator | `x402-fees` | Fee key | `signAction` (sign fee inputs), `listOutputs` |
127
+ | Payment receipt | `x402-revenue` | Payee key | `internalizeAction` (accept payments), `listOutputs` |
128
+
129
+ ### BRC-100 as the API boundary
130
+
131
+ The wallet exposes a BRC-100 interface (or the subset we need). Gateways talk to the wallet exclusively through these methods. They never touch keys directly. The wallet is the security boundary.
132
+
133
+ **BRC-100 methods we need** (subset of the full 28+ method spec):
134
+ - `createAction` — construct and sign transactions (nonce minting, template signing)
135
+ - `signAction` — sign previously created transactions (fee input signing)
136
+ - `internalizeAction` — accept incoming transactions (payment receipt)
137
+ - `listOutputs` — query UTXOs by basket (find nonces, fee UTXOs, revenue)
138
+ - `getPublicKey` — derive keys (BRC-29 derivations for BRC-105, nonce keys)
139
+
140
+ ### Where it lives
141
+
142
+ The `bsv-ruby-sdk` repo (`sgbett/bsv-ruby-sdk`) already has:
143
+ - A monorepo pattern with multiple gemspecs (`bsv-sdk`, `bsv-attest`)
144
+ - A basic wallet at `lib/bsv/wallet/wallet.rb` (single-key, UTXO funding + signing)
145
+ - Full key management including BIP-32 HD derivation
146
+ - Transaction construction with BIP-143 sighash (FORKID)
147
+ - ARC provider
148
+ - BEEF serialisation
149
+
150
+ The `bsv-wallet` gem adds a third gemspec to this repo:
151
+ - BRC-100 interface layer over the existing primitives
152
+ - Basket-based UTXO tracking (nonces, fees, revenue)
153
+ - Multi-key support
154
+ - Builds on the existing `BSV::Wallet::Wallet` as the internal engine
155
+
156
+ ### Deployment options
157
+
158
+ The BRC-100 interface works regardless of deployment:
159
+
160
+ 1. **In-process** — `require 'bsv-wallet'`, gateway calls wallet methods directly. Simplest. Keys in the same process.
161
+ 2. **Local service** — wallet runs as a separate process, gateways call via HTTP. Process isolation.
162
+ 3. **Remote service** — wallet on a different machine. Network boundary. Strongest isolation.
163
+
164
+ Same interface, different transports. Start with in-process, separate later if needed.
165
+
166
+ ### Separation from middleware
167
+
168
+ The wallet gem has a strict public API (BRC-100 methods only). The `x402-rack` gem depends on `bsv-wallet` but only through this interface. The middleware itself (`X402::Middleware`) never talks to the wallet — only gateways do.
169
+
170
+ ```
171
+ x402-rack (no keys, no wallet dependency)
172
+ └── X402::Middleware
173
+ └── X402::BSV::ProofGateway ──→ BSV::Wallet (BRC-100 API)
174
+ └── X402::BSV::PayGateway ────→ BSV::Wallet (BRC-100 API, for ARC only)
175
+ ```
176
+
177
+ ## External Services
178
+
179
+ ### ARC (BSV transaction processor)
180
+ - Broadcasts transactions and returns acceptance/rejection
181
+ - Queries mempool visibility for already-broadcast txs
182
+ - Used by: wallet (via `bsv-sdk` ARC provider)
183
+ - API: https://docs.bsvblockchain.org/important-concepts/details/spv/broadcasting
184
+
185
+ ### Delegator (client-side concern)
186
+ - Adds fee inputs to client-constructed partial txs, signs only its fee inputs
187
+ - Used by: clients (not servers). The server stack never talks to the delegator.
188
+ - Separate service entirely — could be operated by the gateway operator or a third party
189
+ - Could itself be powered by a `bsv-wallet` instance in the "fees" role
190
+
191
+ ## How Identity Flows Through the Stack
192
+
193
+ ```
194
+ Request arrives
195
+
196
+
197
+ BRC-104 Auth Middleware
198
+ │ Verifies x-bsv-auth-* headers
199
+ │ Sets env['brc103.identity_key'] = "02abc..."
200
+ │ Sets env['brc103.certificates'] = [...]
201
+
202
+
203
+ X402 Middleware
204
+ │ Reads route config → protected, costs 100 sats
205
+ │ No proof header → issue challenges
206
+ │ Passes env (including identity) to each gateway
207
+
208
+ ├── PayGateway.challenge_headers(request, route)
209
+ │ Returns Payment-Required header (v2 JSON with BSV in accepts)
210
+
211
+ ├── ProofGateway.challenge_headers(request, route)
212
+ │ Returns X402-Challenge header (merkleworks format)
213
+
214
+ ├── BRC105Gateway.challenge_headers(request, route)
215
+ │ Reads env['brc103.identity_key']
216
+ │ If present → returns x-bsv-payment-* headers (with derivation prefix)
217
+ │ If absent → returns {} (declines — can't work without identity)
218
+
219
+
220
+ 402 Response with all non-empty challenge headers
221
+ ```
222
+
223
+ A client with a BRC-100 wallet and BRC-103 auth gets all three challenge options. A standard x402 v2 client gets the `Payment-Required` header and can pay with BSV. A merkleworks-specific client uses `X402-Challenge`. The client picks whichever it supports.
224
+
225
+ ## How Payment Flows Through the Stack
226
+
227
+ ```
228
+ Request arrives with proof header
229
+
230
+
231
+ BRC-104 Auth Middleware (if present)
232
+ │ Authenticates, sets env['brc103.identity_key']
233
+
234
+
235
+ X402 Middleware
236
+ │ Reads route config → protected, costs 100 sats
237
+ │ Detects proof header
238
+
239
+ ├── Has Payment-Signature? → dispatch to PayGateway.settle!()
240
+ │ Gateway verifies tx, broadcasts via ARC
241
+ │ Returns: allow + settlement result + Payment-Response header
242
+
243
+ ├── Has X402-Proof? → dispatch to ProofGateway.settle!()
244
+ │ Gateway verifies tx, checks mempool via ARC
245
+ │ Returns: allow + settlement result
246
+
247
+ ├── Has x-bsv-payment? → dispatch to BRC105Gateway.settle!()
248
+ │ Gateway verifies derivation + tx via BRC-100 wallet
249
+ │ Returns: allow + settlement result
250
+
251
+
252
+ Allow → forward to application (with receipt headers if provided)
253
+ Deny → return error to client
254
+ ```
255
+
256
+ ## What Each Component Knows
257
+
258
+ | Component | Knows about HTTP | Knows about BSV | Knows about identity | Holds keys |
259
+ |-----------|:---:|:---:|:---:|:---:|
260
+ | BRC-104 Auth Middleware | Yes | Signatures only | Yes — its job | Session keys |
261
+ | X402 Middleware | Yes | No | Passes through | No |
262
+ | ProofGateway | Headers only | Via wallet | No | No — wallet holds them |
263
+ | PayGateway | Headers only | Via wallet | No | No — wallet holds them |
264
+ | BRC-105 Gateway | Headers only | Via wallet | Yes (reads from env) | No — wallet holds them |
265
+ | BSV Wallet | No | Yes — its job | No | Yes — the security boundary |
266
+ | ARC | No | Yes | No | No |
267
+ | Delegator | No | Via wallet | No | No — wallet holds them |
268
+ | Client | Yes | Yes | Optionally | Wallet keys |
269
+
270
+ ## Gem Boundaries
271
+
272
+ | Gem | Repo | Contains |
273
+ |-----|------|---------|
274
+ | `bsv-sdk` | `sgbett/bsv-ruby-sdk` | Primitives — keys, transactions, scripts, ARC provider |
275
+ | `bsv-wallet` | `sgbett/bsv-ruby-sdk` | BRC-100 wallet interface, basket UTXO tracking, multi-key management. Depends on `bsv-sdk`. |
276
+ | `x402-rack` | `sgbett/x402-rack` | X402::Middleware (gatekeeper), gateway interface, X402::BSV::ProofGateway, X402::BSV::PayGateway. Gateways depend on `bsv-wallet`. |
277
+ | `brc104-rack` (future) | Separate | BRC-104 auth middleware |
278
+ | `bsv-x402` (npm) | `sgbett/bsv-x402` | Client-side fetch wrapper, CWI integration |
279
+
280
+ ### Dependency chain
281
+
282
+ ```
283
+ x402-rack
284
+ └── bsv-wallet (BRC-100 interface only)
285
+ └── bsv-sdk (primitives)
286
+ ```
287
+
288
+ The middleware itself has no dependency on `bsv-wallet` or `bsv-sdk`. Only the gateway classes do. A pure middleware deployment (dispatching to remote gateways) wouldn't need the BSV gems at all.
289
+
290
+ ## Design Principles
291
+
292
+ 1. **Each layer handles one concern.** Auth is auth. Payment is payment. Settlement is settlement. They compose, they don't merge.
293
+
294
+ 2. **The gatekeeper is dumb.** It dispatches. It doesn't understand what it's dispatching. Blockchain knowledge lives in gateways.
295
+
296
+ 3. **Gateways are pluggable.** New settlement protocols = new gateway classes. No middleware changes.
297
+
298
+ 4. **Identity is optional and upstream.** Payment gating works without identity. Identity enriches the options (BRC-105) but doesn't gate them.
299
+
300
+ 5. **External services are the gateway's concern.** The middleware never talks to ARC, wallets, or treasuries. Gateways own those relationships.
301
+
302
+ 6. **The client chooses.** Multiple challenge headers, client picks. Payment content negotiation.
303
+
304
+ 7. **State lives on-chain.** No server-side nonce pools, no session tracking, no balance ledgers. The blockchain is the state (with one exception: BRC-105's derivation prefix tracking, which is the BRC-100 wallet's concern).
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,33 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.1
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+
6
+ Style/StringLiterals:
7
+ EnforcedStyle: double_quotes
8
+
9
+ Style/StringLiteralsInInterpolation:
10
+ EnforcedStyle: double_quotes
11
+
12
+ Style/Documentation:
13
+ Enabled: false
14
+
15
+ Metrics/AbcSize:
16
+ Enabled: false
17
+
18
+ Metrics/MethodLength:
19
+ Enabled: false
20
+
21
+ Metrics/CyclomaticComplexity:
22
+ Enabled: false
23
+
24
+ Metrics/ParameterLists:
25
+ Enabled: false
26
+
27
+ Metrics/BlockLength:
28
+ Exclude:
29
+ - "spec/**/*"
30
+ - "*.gemspec"
31
+
32
+ Metrics/CollectionLiteralLength:
33
+ Enabled: false
data/CLAUDE.md ADDED
@@ -0,0 +1,47 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project
6
+
7
+ x402-rack is a Ruby gem providing Rack middleware for the x402 protocol (BSV settlement-gated HTTP). Currently in early development (v0.1.0). Requires Ruby >= 3.1.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ # Install dependencies
13
+ bin/setup
14
+
15
+ # Run tests
16
+ bundle exec rake spec
17
+
18
+ # Run a single test file
19
+ bundle exec rspec spec/x402_spec.rb
20
+
21
+ # Run a single example by line number
22
+ bundle exec rspec spec/x402_spec.rb:4
23
+
24
+ # Lint
25
+ bundle exec rubocop
26
+
27
+ # Lint with auto-fix
28
+ bundle exec rubocop -A
29
+
30
+ # Run all checks (tests + lint) — this is the CI default
31
+ bundle exec rake
32
+ ```
33
+
34
+ ## Architecture
35
+
36
+ Standard Ruby gem layout generated by `bundle gem`:
37
+
38
+ - `lib/x402.rb` — main entry point, defines `X402` module
39
+ - `lib/x402/version.rb` — version constant
40
+ - `sig/x402.rbs` — RBS type signatures
41
+ - `x402-rack.gemspec` — gem specification (dependencies defined here, not in Gemfile)
42
+
43
+ ## Code Style
44
+
45
+ - Double quotes for strings (enforced by RuboCop)
46
+ - `frozen_string_literal: true` magic comment on all Ruby files
47
+ - Target Ruby version: 3.1
data/DESIGN.md ADDED
@@ -0,0 +1,216 @@
1
+ # x402-rack Design Notes (DRAFT)
2
+
3
+ ## Architecture
4
+
5
+ ### Middleware as Dispatcher (`X402::Middleware`)
6
+
7
+ The Rack middleware is a **pure dispatcher** — the gatekeeper. It has no blockchain knowledge. It:
8
+
9
+ 1. Matches incoming requests against protected routes
10
+ 2. Polls each configured gateway for challenge headers, returns all of them in the 402 response
11
+ 3. Checks which proof/payment header the client sent, dispatches to the matching gateway
12
+ 4. The gateway returns allow/deny — the middleware serves or rejects accordingly
13
+
14
+ The middleware never decodes transactions, checks mempool, broadcasts, or interacts with any blockchain network. It manages HTTP headers, route matching, and dispatch.
15
+
16
+ **The gatekeeper MUST NOT sign transactions or hold private keys.**
17
+
18
+ ### Gateways (`X402::BSV::ProofGateway`, `X402::BSV::PayGateway`)
19
+
20
+ Gateways are pluggable backends that handle chain-specific settlement. They **can** hold keys and sign transactions — they are separate components from the gatekeeper. Each gateway:
21
+
22
+ - Builds challenge data (including partial transaction templates)
23
+ - Verifies and settles proofs
24
+ - Interacts with ARC and/or a treasury service via the BSV wallet
25
+
26
+ The gateway interface:
27
+
28
+ ```ruby
29
+ # #challenge_headers(rack_request, route) → Hash
30
+ # #proof_header_names → Array<String>
31
+ # #settle!(header_name, proof_payload, rack_request, route) → result
32
+ ```
33
+
34
+ The boundary test: could someone write `X402::EVM::Gateway` implementing this interface without touching `lib/x402/`? If yes, the separation is correct.
35
+
36
+ ### Multi-Protocol Support
37
+
38
+ Different x402 ecosystems use different HTTP headers. A server can send **multiple challenge headers** simultaneously — the client picks the one it can satisfy. This is payment content negotiation.
39
+
40
+ | Scheme | Challenge header | Proof header | Receipt header |
41
+ |--------|-----------------|--------------|----------------|
42
+ | BSV-pay (ours) | `Payment-Required` | `Payment-Signature` | `Payment-Response` |
43
+ | BSV-proof (merkleworks) | `X402-Challenge` | `X402-Proof` | — |
44
+
45
+ Our PayGateway uses the Coinbase v2 headers (`Payment-*`) — the standard x402 ecosystem language. The ProofGateway uses the merkleworks `X402-*` headers. Header namespaces are reserved per ecosystem: `Payment-*` (Coinbase v2 / ours), `X402-*` (merkleworks), `x-bsv-*` (BRC-105 / BSV Association).
46
+
47
+ ## Unified Template Model
48
+
49
+ ### Both gateways produce partial transaction templates
50
+
51
+ The challenge includes a **partial transaction template** that the client extends by adding funding inputs (and optionally change outputs). This model unifies the two BSV schemes.
52
+
53
+ **Base behaviour** (`X402::BSV::Gateway`): build a partial tx with the payment output (amount to payee) and an OP_RETURN request binding output.
54
+
55
+ **ProofGateway override**: prepends the nonce UTXO input at index 0, signed with `SIGHASH_SINGLE | ANYONECANPAY | FORKID (0xC3)`. This locks the payment output (output 0) while allowing the client to append inputs and outputs freely.
56
+
57
+ **PayGateway**: inherits the base behaviour. Payment output + OP_RETURN binding, no nonce.
58
+
59
+ The client's job is identical regardless of scheme: add funding inputs, sign, and either broadcast (BSV-proof) or hand to the server (BSV-pay). The delegator fits the same way in both flows.
60
+
61
+ ### Progressive enhancement via `extra.partialTx`
62
+
63
+ For the PayGateway's `Payment-Required` challenge (Coinbase v2 format), the partial tx template is carried in the `extra` field of the `accepts` entry:
64
+
65
+ ```json
66
+ {
67
+ "x402Version": 2,
68
+ "resource": { "url": "/api/expensive" },
69
+ "accepts": [
70
+ {
71
+ "scheme": "exact",
72
+ "network": "bsv:mainnet",
73
+ "amount": "100",
74
+ "asset": "BSV",
75
+ "payTo": "1A1zP1...",
76
+ "maxTimeoutSeconds": 60,
77
+ "extra": {
78
+ "partialTx": "<base64 of partial tx template>"
79
+ }
80
+ }
81
+ ]
82
+ }
83
+ ```
84
+
85
+ **Basic client** (any x402 v2 client): ignores `extra.partialTx`, constructs a tx from scratch using `payTo` + `amount`.
86
+
87
+ **Smart client** (BSV-aware): reads `extra.partialTx`, extends the template by adding funding inputs and signing.
88
+
89
+ The template is an optimisation, not a requirement. `payTo` + `amount` are always sufficient.
90
+
91
+ ### Request binding via OP_RETURN
92
+
93
+ The partial tx template includes an OP_RETURN output binding the payment to the specific request:
94
+
95
+ ```
96
+ Output 0: payment (amount to payee)
97
+ Output 1: OP_RETURN <SHA256(method + path + query)>
98
+ ```
99
+
100
+ At settlement, the gateway recomputes the hash and verifies it matches. Prevents template redirection between endpoints. Cheap (~30 bytes), on-chain, verifiable. Configurable strict/permissive mode.
101
+
102
+ ### Why 0xC3 for the nonce signature
103
+
104
+ `SIGHASH_SINGLE | ANYONECANPAY | FORKID`:
105
+ - `SIGHASH_SINGLE`: commits only to `output[input_index]` — the nonce at input 0 protects only output 0 (the payment)
106
+ - `ANYONECANPAY`: excludes other inputs — funding and fee inputs can be appended freely
107
+ - `FORKID`: BSV fork ID flag (required)
108
+
109
+ Using `0xC1` (`SIGHASH_ALL | ANYONECANPAY`) would commit to ALL outputs, breaking extensibility.
110
+
111
+ ## Two BSV Schemes
112
+
113
+ ### BSV-proof (merkleworks x402 spec)
114
+
115
+ Client broadcasts, server checks mempool. Proof-of-payment model.
116
+
117
+ **Headers**: `X402-Challenge` / `X402-Proof`
118
+
119
+ **Challenge**: merkleworks JSON format including a pre-signed partial tx template (Profile B) with nonce UTXO at input 0 signed with `0xC3`, payment output at output 0, plus request binding metadata, expiry, and `require_mempool_accept: true`.
120
+
121
+ **Settlement**: gateway verifies tx structure, checks nonce spent at input 0, checks payment output, queries ARC for mempool visibility.
122
+
123
+ **Why client broadcasts** (per Rui at merkleworks): broadcasting is settlement, not authorisation. Server-side broadcast pushes the server towards a stateful payment processor. Client-side broadcast keeps it stateless.
124
+
125
+ **Requires**: treasury (nonce provision + template signing) + ARC (mempool queries).
126
+
127
+ ### BSV-pay (our BSV-native scheme)
128
+
129
+ Server broadcasts via ARC. Uses Coinbase v2 header spec.
130
+
131
+ **Headers**: `Payment-Required` / `Payment-Signature` / `Payment-Response`
132
+
133
+ **Challenge**: Coinbase v2 `PaymentRequired` with BSV in `accepts` array, `extra.partialTx` carrying the template (payment output + OP_RETURN binding).
134
+
135
+ **Settlement**: gateway verifies payment output, verifies OP_RETURN binding, broadcasts to ARC (`X-WaitFor: SEEN_ON_NETWORK`, 5s timeout). ARC 200 → allow. ARC error → relay to client.
136
+
137
+ **No nonces needed**: ARC is the replay gate. Each tx can only be accepted once.
138
+
139
+ **Requires**: ARC only. No treasury, no nonce provision.
140
+
141
+ ### Comparison
142
+
143
+ | | BSV-proof (merkleworks) | BSV-pay (ours) |
144
+ |---|---|---|
145
+ | Header spec | Merkleworks `X402-*` | Coinbase v2 `Payment-*` |
146
+ | Challenge header | `X402-Challenge` | `Payment-Required` |
147
+ | Proof header | `X402-Proof` | `Payment-Signature` |
148
+ | Receipt header | — | `Payment-Response` |
149
+ | Template contains | Nonce input (signed 0xC3) + payment output | Payment output + OP_RETURN binding |
150
+ | Who broadcasts | Client | Server (via ARC) |
151
+ | Nonce needed | Yes (challenge binding) | No (ARC is replay gate) |
152
+ | Request binding | Yes (in challenge metadata) | Yes (OP_RETURN in template) |
153
+ | Settlement check | Mempool visibility query | ARC broadcast response |
154
+ | Treasury needed | Yes | No |
155
+ | Minimum infrastructure | Treasury + ARC | ARC only |
156
+ | Ecosystem compatibility | Merkleworks BSV clients | Any x402 v2 client |
157
+
158
+ ## Component Boundaries
159
+
160
+ | Component | Responsibility | Keys? |
161
+ |-----------|---------------|-------|
162
+ | **Gatekeeper** (`X402::Middleware`) | HTTP dispatch, route matching | No — MUST NOT hold keys |
163
+ | **Gateway** (`X402::BSV::*Gateway`) | Challenge templates, settlement, ARC interaction | Via wallet |
164
+ | **BSV Wallet** (`bsv-wallet` gem) | Key management, UTXO tracking, signing | Yes — the security boundary |
165
+ | **Treasury** (wallet role) | Mints nonce UTXOs, signs templates | Via wallet's nonce basket |
166
+ | **Delegator** (separate service) | Adds fee inputs, signs only fee inputs | Yes — but not our concern |
167
+ | **Client** (browser + CWI wallet) | Extends template, signs funding inputs | Yes — client's wallet |
168
+
169
+ ### Server-side wallet
170
+
171
+ The `bsv-wallet` gem (in the `sgbett/bsv-ruby-sdk` monorepo) provides a BRC-100 interface. Gateways talk to the wallet exclusively through this API — they never touch keys directly. The wallet is the security boundary.
172
+
173
+ One wallet, multiple roles via baskets:
174
+
175
+ | Role | Basket | Operations |
176
+ |------|--------|------------|
177
+ | Treasury | `x402-nonces` | `createAction` (mint nonces, sign templates), `listOutputs` |
178
+ | Delegator | `x402-fees` | `signAction` (sign fee inputs), `listOutputs` |
179
+ | Payment receipt | `x402-revenue` | `internalizeAction` (accept payments), `listOutputs` |
180
+
181
+ ### Dependency chain
182
+
183
+ ```
184
+ x402-rack (no keys, no wallet dependency in middleware)
185
+ └── X402::BSV::*Gateway → bsv-wallet (BRC-100 interface)
186
+ └── bsv-sdk (primitives)
187
+ ```
188
+
189
+ ## Ecosystem Context
190
+
191
+ **Coinbase x402 v2** (broad ecosystem): client signs authorisation, facilitator broadcasts. Headers: `Payment-Required` / `Payment-Signature` / `Payment-Response`.
192
+
193
+ **Merkleworks x402** (BSV-specific): client broadcasts, server checks mempool. Headers: `X402-Challenge` / `X402-Proof`.
194
+
195
+ **BRC-105** (BSV Association BRC, future): mutual auth (BRC-103) + derivation-based payments. Headers: `x-bsv-payment-*`.
196
+
197
+ Our middleware supports all header conventions via the multi-gateway dispatch model. Our PayGateway speaks the standard Coinbase v2 language, making BSV a first-class citizen in the broader x402 ecosystem.
198
+
199
+ ## Client Side
200
+
201
+ The x402 flow requires a client that intercepts 402 responses, parses challenges, extends transaction templates, handles fee delegation, and presents proof/payment. This is handled by [`bsv-x402`](https://www.npmjs.com/package/bsv-x402) — a separate JavaScript/TypeScript library ([`sgbett/bsv-x402`](https://github.com/sgbett/bsv-x402) on GitHub).
202
+
203
+ The client wraps `fetch()` and uses BRC-100 (`window.CWI`) to interact with compliant BSV wallets for transaction construction and signing. See that project's documentation for architecture and integration details.
204
+
205
+ ## Current State
206
+
207
+ The middleware (`X402::Middleware`), configuration, and protocol layer (challenge/proof structures, request binding, base64url encoding) are implemented. BSV-specific logic currently lives in `X402::Verification::SettlementChecks` and needs to migrate into the gateway classes.
208
+
209
+ Next steps:
210
+ 1. Extract the gateway interface from the middleware
211
+ 2. Implement `X402::BSV::Gateway` base class (payment output + OP_RETURN template)
212
+ 3. Implement `X402::BSV::ProofGateway` (merkleworks compatibility)
213
+ 4. Implement `X402::BSV::PayGateway` (BSV-native, ARC broadcast, Coinbase v2 headers)
214
+ 5. Refactor middleware to multi-gateway dispatch
215
+
216
+ See [`.claude/plans/20260325-bsv-module.md`](.claude/plans/20260325-bsv-module.md) for the detailed implementation plan and [`.claude/plans/20260326-rack-stack-architecture.md`](.claude/plans/20260326-rack-stack-architecture.md) for the full rack stack architecture.
data/LICENSE.txt ADDED
@@ -0,0 +1,56 @@
1
+ Open BSV License Version 5 – granted by BSV Association, Grafenauweg 6, 6300
2
+ Zug, Switzerland (CHE-427.008.338) ("Licensor"), to you as a user (henceforth
3
+ "You", "User" or "Licensee").
4
+
5
+ For the purposes of this license, the definitions below have the following
6
+ meanings:
7
+
8
+ "Bitcoin Protocol" means the protocol implementation, cryptographic rules,
9
+ network protocols, and consensus mechanisms in the Bitcoin White Paper as
10
+ described here https://protocol.bsvblockchain.org.
11
+
12
+ "Bitcoin White Paper" means the paper entitled 'Bitcoin: A Peer-to-Peer
13
+ Electronic Cash System' published by 'Satoshi Nakamoto' in October 2008.
14
+
15
+ "BSV Blockchains" means:
16
+ (a) the Bitcoin blockchain containing block height #556767 with the hash
17
+ "000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b" and
18
+ that contains the longest honest persistent chain of blocks which has been
19
+ produced in a manner which is consistent with the rules set forth in the
20
+ Network Access Rules; and
21
+ (b) the test blockchains that contain the longest honest persistent chains of
22
+ blocks which has been produced in a manner which is consistent with the
23
+ rules set forth in the Network Access Rules.
24
+
25
+ "Network Access Rules" or "Rules" means the set of rules regulating the
26
+ relationship between BSV Association and the nodes on BSV based on the Bitcoin
27
+ Protocol rules and those set out in the Bitcoin White Paper, and available here
28
+ https://bsvblockchain.org/network-access-rules.
29
+
30
+ "Software" means the software the subject of this licence, including any/all
31
+ intellectual property rights therein and associated documentation files.
32
+
33
+ BSV Association grants permission, free of charge and on a non-exclusive and
34
+ revocable basis, to any person obtaining a copy of the Software to deal in the
35
+ Software without restriction, including without limitation the rights to use,
36
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
37
+ Software, and to permit persons to whom the Software is furnished to do so,
38
+ subject to and conditioned upon the following conditions:
39
+
40
+ 1 - The text "© BSV Association," and this license shall be included in all
41
+ copies or substantial portions of the Software.
42
+ 2 - The Software, and any software that is derived from the Software or parts
43
+ thereof, must only be used on the BSV Blockchains.
44
+
45
+ For the avoidance of doubt, this license is granted subject to and conditioned
46
+ upon your compliance with these terms only. In the event of non-compliance, the
47
+ license shall extinguish and you can be enjoined from violating BSV's
48
+ intellectual property rights (incl. damages and similar related claims).
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES REGARDING ENTITLEMENT,
52
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
53
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS THEREOF BE LIABLE FOR ANY CLAIM,
54
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
55
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
56
+ DEALINGS IN THE SOFTWARE.