x402-rack 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd77486c75afc23677145007680438a0a261f168a6314bc5e8038de1429d51b0
4
- data.tar.gz: ce8eaeff559f9a7f376991fc33c4233d3c85883e4f71000c4ab609e15fd60eb8
3
+ metadata.gz: 7c88a0b6770421ac5fa4d83a410a9951f9544af70325fe467bc29676b7d0957f
4
+ data.tar.gz: b0f8f30ff3a63b6a83794a148e4e8e8aed60555e337c70a6925539147b2a4850
5
5
  SHA512:
6
- metadata.gz: 9b692baf1bfc107e95dabeed52cb672447e578b25d7d135a2983d9caa61c719ab9b0e4552bf5ea57ccb28d9f0a06b2ab873ced1bbb8630c18d84e63452e2d992
7
- data.tar.gz: ecec6258c8b30604a33f4894af7dec5477e929eafc2340a0de88417e2a89f56bb3b8469934c4087c90568f6b9559d89f803cde8ff17aea537aded30df9ed5d26
6
+ metadata.gz: 8208b0343e9f84a4d7f998a42d574627f92c6457f40a4d8732aa3ed6ff7383789410fc895a43118db49e45bde9a31fb79283524e3b7c4677dcff1465d92119cd
7
+ data.tar.gz: d65d2ed290d6c097a3a0bccfda18f2634c458e59dace5b4a86ae478616525483adbeb5ba7b62d112f2bfd4475c0a0668772aa1baf2c92e16c52f547bda6f591e
@@ -302,3 +302,14 @@ The middleware itself has no dependency on `bsv-wallet` or `bsv-sdk`. Only the g
302
302
  6. **The client chooses.** Multiple challenge headers, client picks. Payment content negotiation.
303
303
 
304
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).
305
+
306
+ ## Future: Wallet Dashboard UI
307
+
308
+ A mountable Rack endpoint (e.g. `/wallet`) serving a simple web UI for the server-side wallet. Reads from the same `bsv-wallet` instance the gateways use, providing operator visibility into:
309
+
310
+ - **Balances** — per-basket totals (nonces, fees, revenue)
311
+ - **Transaction history** — recent actions with labels, status
312
+ - **Output browser** — UTXOs by basket with tags, spendable status
313
+ - **Certificate management** — issued/held certificates
314
+
315
+ Similar pattern to Sidekiq's web UI or Rails' ActiveStorage dashboard — an optional mountable app that gives operators a window into the wallet without touching the settlement flow. The wallet gem provides the engine; this provides the dashboard. Not a user-facing wallet UI — an operator tool for monitoring and debugging the payment infrastructure.
data/.rubocop.yml CHANGED
@@ -29,5 +29,8 @@ Metrics/BlockLength:
29
29
  - "spec/**/*"
30
30
  - "*.gemspec"
31
31
 
32
+ Metrics/ClassLength:
33
+ Enabled: false
34
+
32
35
  Metrics/CollectionLiteralLength:
33
36
  Enabled: false
data/CLAUDE.md CHANGED
@@ -37,6 +37,12 @@ Standard Ruby gem layout generated by `bundle gem`:
37
37
 
38
38
  - `lib/x402.rb` — main entry point, defines `X402` module
39
39
  - `lib/x402/version.rb` — version constant
40
+ - `lib/x402/middleware.rb` — pure dispatcher (no blockchain knowledge)
41
+ - `lib/x402/bsv/gateway.rb` — base class for template-based gateways
42
+ - `lib/x402/bsv/pay_gateway.rb` — Coinbase v2 headers, server broadcasts
43
+ - `lib/x402/bsv/proof_gateway.rb` — merkleworks headers, client broadcasts
44
+ - `lib/x402/bsv/brc105_gateway.rb` — BSV Association BRC-105, BRC-29 derivation (no inheritance from Gateway)
45
+ - `lib/x402/bsv/prefix_store.rb` — pluggable replay protection for BRC-105 derivation prefixes
40
46
  - `sig/x402.rbs` — RBS type signatures
41
47
  - `x402-rack.gemspec` — gem specification (dependencies defined here, not in Gemfile)
42
48
 
data/DESIGN.md CHANGED
@@ -1,216 +1,52 @@
1
- # x402-rack Design Notes (DRAFT)
1
+ # x402-rack Design
2
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`.
3
+ Full documentation is in [`docs/`](docs/). This file serves as an index.
86
4
 
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 |
5
+ ## Architecture
157
6
 
158
- ## Component Boundaries
7
+ The middleware is a pure dispatcher — no blockchain knowledge, no keys. Gateways handle settlement.
159
8
 
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 |
9
+ [docs/architecture.md](docs/architecture.md)
168
10
 
169
- ### Server-side wallet
11
+ ## Settlement Schemes
170
12
 
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.
13
+ Three BSV payment schemes:
172
14
 
173
- One wallet, multiple roles via baskets:
15
+ - **BSV-pay** server broadcasts via ARC. Coinbase v2 headers. Minimal infrastructure.
16
+ → [docs/schemes/bsv-pay.md](docs/schemes/bsv-pay.md)
174
17
 
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` |
18
+ - **BSV-proof** client broadcasts, server checks mempool. Merkleworks headers. Nonce-bound.
19
+ → [docs/schemes/bsv-proof.md](docs/schemes/bsv-proof.md)
180
20
 
181
- ### Dependency chain
21
+ - **BRC-105** — BRC-29 derived addresses, AtomicBEEF transactions. BSV Association headers. Optional BRC-103 auth.
22
+ → [docs/schemes/brc-105.md](docs/schemes/brc-105.md)
182
23
 
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
- ```
24
+ ## Security
188
25
 
189
- ## Ecosystem Context
26
+ HMAC payToSig, nonce provenance verification (0xC3), OP_RETURN binding, threat model.
190
27
 
191
- **Coinbase x402 v2** (broad ecosystem): client signs authorisation, facilitator broadcasts. Headers: `Payment-Required` / `Payment-Signature` / `Payment-Response`.
28
+ [docs/security.md](docs/security.md)
192
29
 
193
- **Merkleworks x402** (BSV-specific): client broadcasts, server checks mempool. Headers: `X402-Challenge` / `X402-Proof`.
30
+ ## Operations
194
31
 
195
- **BRC-105** (BSV Association BRC, future): mutual auth (BRC-103) + derivation-based payments. Headers: `x-bsv-payment-*`.
32
+ - **Deployment**: configuration, ARC setup, rate limiting [docs/operations/deployment.md](docs/operations/deployment.md)
33
+ - **Performance**: benchmarks, scaling trade-offs, ARC bottleneck → [docs/operations/performance.md](docs/operations/performance.md)
34
+ - **Treasury**: nonce UTXO lifecycle, expiry, miner sweep → [docs/operations/treasury.md](docs/operations/treasury.md)
196
35
 
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.
36
+ ## Ecosystem
198
37
 
199
- ## Client Side
38
+ Coinbase v2, merkleworks, BRC-105. Header namespaces. Our position.
200
39
 
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).
40
+ [docs/ecosystem.md](docs/ecosystem.md)
202
41
 
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.
42
+ ## Client Integration
204
43
 
205
- ## Current State
44
+ bsv-x402, BRC-100/CWI, BSV Browser, retry logic, fee delegation.
206
45
 
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.
46
+ [docs/client-integration.md](docs/client-integration.md)
208
47
 
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
48
+ ## Process Flows
215
49
 
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.
50
+ - **PayGateway**: [docs/process-flow/pay-gateway.md](docs/process-flow/pay-gateway.md)
51
+ - **ProofGateway**: [docs/process-flow/proof-gateway.md](docs/process-flow/proof-gateway.md)
52
+ - **BRC105Gateway**: [docs/process-flow/brc105-gateway.md](docs/process-flow/brc105-gateway.md)
data/README.md CHANGED
@@ -32,6 +32,12 @@ X402.configure do |config|
32
32
  X402::BSV::PayGateway.new(
33
33
  arc_url: "https://arc.taal.com",
34
34
  arc_api_key: "..."
35
+ ),
36
+ # BRC-105 gateway (BSV Association payment protocol)
37
+ X402::BSV::BRC105Gateway.new(
38
+ key_deriver: BSV::Wallet::KeyDeriver.new(server_private_key),
39
+ prefix_store: X402::BSV::PrefixStore::Memory.new,
40
+ arc_client: arc_client
35
41
  )
36
42
  ]
37
43
 
@@ -49,12 +55,13 @@ use X402::Middleware
49
55
  4. Middleware dispatches the proof to the matching gateway for settlement
50
56
  5. Gateway verifies and settles — middleware serves or rejects
51
57
 
52
- Two BSV settlement schemes are supported:
58
+ Three BSV settlement schemes are supported:
53
59
 
54
60
  - **BSV-pay** (Coinbase v2 headers) — server broadcasts via ARC. No nonces, minimal infrastructure.
55
61
  - **BSV-proof** (merkleworks x402) — client broadcasts, server checks mempool. Nonce-bound, request-binding.
62
+ - **BRC-105** (BSV Association `x-bsv-*` headers) — BRC-29 key derivation for unique payment addresses. Works standalone or composes with BRC-103 mutual authentication.
56
63
 
57
- Both gateways produce partial transaction templates that clients extend by adding funding inputs. See [DESIGN.md](DESIGN.md) for details.
64
+ BSV-pay and BSV-proof produce partial transaction templates that clients extend. BRC-105 uses a different model — the client builds the entire transaction using BRC-29 derived addresses. See [DESIGN.md](DESIGN.md) for details.
58
65
 
59
66
  ## Development
60
67
 
@@ -0,0 +1,119 @@
1
+ # Architecture
2
+
3
+ ## Middleware as Dispatcher (`X402::Middleware`)
4
+
5
+ The Rack middleware is a **pure dispatcher** — the gatekeeper. It has no blockchain knowledge. It:
6
+
7
+ 1. Matches incoming requests against protected routes
8
+ 2. Polls each configured gateway for challenge headers, returns all of them in the 402 response
9
+ 3. Checks which proof/payment header the client sent, dispatches to the matching gateway
10
+ 4. The gateway returns allow/deny — the middleware serves or rejects accordingly
11
+
12
+ The middleware never decodes transactions, checks mempool, broadcasts, or interacts with any blockchain network. It manages HTTP headers, route matching, and dispatch.
13
+
14
+ **The gatekeeper MUST NOT sign transactions or hold private keys.**
15
+
16
+ ## Gateways
17
+
18
+ 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:
19
+
20
+ - Builds challenge data (including partial transaction templates)
21
+ - Verifies and settles proofs
22
+ - Interacts with ARC and/or a treasury service via the BSV wallet
23
+
24
+ ### Gateway Interface
25
+
26
+ ```ruby
27
+ # #challenge_headers(rack_request, route) → Hash
28
+ # #proof_header_names → Array<String>
29
+ # #settle!(header_name, proof_payload, rack_request, route) → result
30
+ ```
31
+
32
+ The boundary test: could someone write `X402::EVM::Gateway` implementing this interface without touching `lib/x402/`? If yes, the separation is correct.
33
+
34
+ ### Built-in Gateways
35
+
36
+ - **`X402::BSV::PayGateway`** — Coinbase v2 headers, server broadcasts via ARC. See [schemes/bsv-pay.md](schemes/bsv-pay.md).
37
+ - **`X402::BSV::ProofGateway`** — merkleworks headers, client broadcasts, server checks mempool. See [schemes/bsv-proof.md](schemes/bsv-proof.md).
38
+ - **`X402::BSV::BRC105Gateway`** — BSV Association `x-bsv-*` headers, BRC-29 derived addresses, AtomicBEEF transactions. See [schemes/brc-105.md](schemes/brc-105.md).
39
+
40
+ ## Payment Content Negotiation
41
+
42
+ Different x402 ecosystems use different HTTP headers. A server can send **multiple challenge headers** simultaneously — the client picks the one it can satisfy.
43
+
44
+ | Scheme | Challenge headers | Proof header | Receipt header |
45
+ |--------|------------------|--------------|----------------|
46
+ | BSV-pay (ours) | `Payment-Required` | `Payment-Signature` | `Payment-Response` |
47
+ | BSV-proof (merkleworks) | `X402-Challenge` | `X402-Proof` | — |
48
+ | BRC-105 (BSV Association) | `x-bsv-payment-satoshis-required`, `x-bsv-payment-derivation-prefix`, `x-bsv-payment-identity-key`* | `x-bsv-payment` | `x-bsv-payment-result` |
49
+
50
+ \* `x-bsv-payment-identity-key` is omitted when BRC-103 middleware is present upstream.
51
+
52
+ Header namespaces are reserved per ecosystem:
53
+ - `Payment-*` — Coinbase v2 / our PayGateway
54
+ - `X402-*` — merkleworks / our ProofGateway
55
+ - `x-bsv-*` — BRC-105 / BSV Association (our BRC105Gateway)
56
+
57
+ ## Transaction Models
58
+
59
+ ### Template-based (PayGateway, ProofGateway)
60
+
61
+ Both template-based gateways produce **partial transaction templates** that the client extends by adding funding inputs (and optionally change outputs).
62
+
63
+ **Base behaviour** (`X402::BSV::Gateway`): build a partial tx with the payment output (amount to payee) and an OP_RETURN request binding output.
64
+
65
+ **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.
66
+
67
+ **PayGateway**: inherits the base behaviour. Payment output + OP_RETURN binding, no nonce.
68
+
69
+ The client's job is identical for template-based gateways: add funding inputs, sign, and either broadcast (BSV-proof) or hand to the server (BSV-pay).
70
+
71
+ ### Derivation-based (BRC105Gateway)
72
+
73
+ BRC105Gateway uses a fundamentally different approach — **no partial transaction template**. Instead:
74
+
75
+ 1. The server advertises a derivation prefix (random nonce) and its identity key
76
+ 2. The client derives a unique payment address using BRC-29 (BRC-42 key derivation with protocol ID `[2, "3241645161d8"]` and key ID `"#{prefix} #{suffix}"`)
77
+ 3. The client builds the entire transaction independently, paying to the derived address
78
+ 4. The server re-derives the expected address and verifies the payment output
79
+
80
+ This eliminates the need for OP_RETURN binding, payTo HMAC, or any shared transaction state. BRC105Gateway does not inherit from `Gateway` — it uses composition via `KeyDeriver`.
81
+
82
+ ### Request Binding via OP_RETURN
83
+
84
+ ```
85
+ Output 0: payment (amount to payee)
86
+ Output 1: OP_RETURN "x402" <SHA256(method + path + query)>
87
+ ```
88
+
89
+ The `x402` protocol tag makes payments discoverable on-chain. The SHA-256 hash binds the payment to the specific HTTP request. Configurable strict/permissive mode.
90
+
91
+ ### Why 0xC3 for the Nonce Signature
92
+
93
+ `SIGHASH_SINGLE | ANYONECANPAY | FORKID`:
94
+ - `SIGHASH_SINGLE`: commits only to `output[input_index]` — the nonce at input 0 protects only output 0 (the payment)
95
+ - `ANYONECANPAY`: excludes other inputs — funding and fee inputs can be appended freely
96
+ - `FORKID`: BSV fork ID flag (required)
97
+
98
+ Using `0xC1` (`SIGHASH_ALL | ANYONECANPAY`) would commit to ALL outputs, breaking extensibility.
99
+
100
+ ## Component Boundaries
101
+
102
+ | Component | Responsibility | Keys? |
103
+ |-----------|---------------|-------|
104
+ | **Gatekeeper** (`X402::Middleware`) | HTTP dispatch, route matching | No — MUST NOT hold keys |
105
+ | **Gateway** (`X402::BSV::*Gateway`) | Challenge templates, settlement, ARC interaction | Via wallet |
106
+ | **BSV Wallet** (`bsv-wallet` gem) | Key management, UTXO tracking, signing | Yes — the security boundary |
107
+ | **Treasury** (wallet role) | Mints nonce UTXOs, signs templates | Via wallet's nonce basket |
108
+ | **Delegator** (separate service) | Adds fee inputs, signs only fee inputs | Yes — but not our concern |
109
+ | **Client** (browser + CWI wallet) | Extends template, signs funding inputs | Yes — client's wallet |
110
+
111
+ ### Dependency Chain
112
+
113
+ ```
114
+ x402-rack (no keys, no wallet dependency in middleware)
115
+ └── X402::BSV::*Gateway → bsv-wallet (BRC-100 interface)
116
+ └── bsv-sdk (primitives)
117
+ ```
118
+
119
+ The middleware itself has no dependency on `bsv-wallet` or `bsv-sdk`. Only the gateway classes do.
@@ -0,0 +1,98 @@
1
+ # Client Integration
2
+
3
+ ## bsv-x402 (JavaScript/TypeScript)
4
+
5
+ The client library wraps `fetch()` and handles the x402 payment flow transparently:
6
+
7
+ ```js
8
+ import { x402Fetch } from 'bsv-x402'
9
+
10
+ const response = await x402Fetch('https://api.example.com/paid-endpoint')
11
+ ```
12
+
13
+ When the server responds with `402 Payment Required`, the library:
14
+
15
+ 1. Parses the challenge header (`Payment-Required` or `X402-Challenge`)
16
+ 2. Constructs a payment transaction via `window.CWI` (BRC-100 wallet)
17
+ 3. Extends the `extra.partialTx` template if present (or builds from scratch)
18
+ 4. Broadcasts the transaction (ProofGateway) or hands it to the server (PayGateway)
19
+ 5. Retries the original request with the proof header
20
+
21
+ The app developer just uses `x402Fetch` in place of `fetch`. The UI doesn't flicker — the data just arrives.
22
+
23
+ **Repository**: [sgbett/bsv-x402](https://github.com/sgbett/bsv-x402)
24
+ **npm**: `bsv-x402`
25
+
26
+ ## BRC-100 and `window.CWI`
27
+
28
+ [BRC-100](https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0100.md) is a vendor-neutral wallet-to-application interface. Compliant wallets inject a `window.CWI` object into web pages — analogous to `window.ethereum` in the Ethereum ecosystem.
29
+
30
+ Key methods used by the x402 client:
31
+ - `createAction()` — construct and sign transactions
32
+ - `signAction()` — sign previously created transactions
33
+ - `listOutputs()` — find available UTXOs for funding
34
+
35
+ Because this uses BRC-100 (not a browser-specific API), it works with any compliant wallet.
36
+
37
+ ## BSV Browser
38
+
39
+ [BSV Browser](https://github.com/bsv-blockchain/bsv-browser) is the reference BRC-100 wallet implementation. It exposes `window.CWI` and is the primary target for testing the end-to-end flow.
40
+
41
+ The planned integration path:
42
+ 1. User visits a site protected by x402-rack
43
+ 2. BSV Browser's `window.CWI` is available
44
+ 3. `bsv-x402` intercepts the 402 and calls `CWI.createAction()`
45
+ 4. Payment happens seamlessly — the user sees the content load
46
+
47
+ ## Client Behaviour by Scheme
48
+
49
+ ### BRC105Gateway (BRC-105)
50
+
51
+ 1. Client receives `x-bsv-payment-satoshis-required`, `x-bsv-payment-derivation-prefix`, and `x-bsv-payment-identity-key` headers
52
+ 2. Client chooses a random derivation suffix
53
+ 3. Derives payment address using BRC-29: `KeyDeriver.derive_public_key([2, "3241645161d8"], "#{prefix} #{suffix}", server_identity_key)`
54
+ 4. Builds a transaction paying to the derived P2PKH address
55
+ 5. Encodes the transaction as AtomicBEEF (BRC-95), base64
56
+ 6. Sends `x-bsv-payment` header with JSON: `{ "derivationPrefix": "...", "derivationSuffix": "...", "transaction": "<base64 AtomicBEEF>" }`
57
+ 7. Server verifies derivation, broadcasts via ARC, returns `x-bsv-payment-result`
58
+
59
+ **BRC-103 authenticated mode**: the client already has the server's identity key from the BRC-103 handshake — the `x-bsv-payment-identity-key` header is omitted. The client's authenticated identity key is used as the BRC-29 counterparty, binding the payment to the mutual-auth session.
60
+
61
+ **BRC-100 wallet integration**: BRC-105 clients can use `wallet.createAction()` to build the transaction and `wallet.internalizeAction()` on the server to process it. The derivation prefix/suffix flow integrates natively with BRC-100's payment handling.
62
+
63
+ ### PayGateway (BSV-pay)
64
+
65
+ 1. Client receives `Payment-Required` header
66
+ 2. Reads `extra.partialTx` template (if present)
67
+ 3. Extends template with funding inputs, signs
68
+ 4. Sends `Payment-Signature` header with the raw tx
69
+ 5. Server broadcasts via ARC
70
+ 6. Client receives 200 + `Payment-Response` receipt
71
+
72
+ **On failure**: present "payment failed, retry?" option to the user. This is the simple deployment path.
73
+
74
+ ### ProofGateway (BSV-proof)
75
+
76
+ 1. Client receives `X402-Challenge` header
77
+ 2. Reads `partial_tx_b64` template (Profile B, if present)
78
+ 3. Extends template with funding inputs, signs
79
+ 4. **Broadcasts the transaction to the BSV network**
80
+ 5. Sends `X402-Proof` header with txid + rawtx
81
+ 6. Server checks mempool, serves content
82
+
83
+ **On failure**: implement automatic retry logic. The client has already broadcast — the tx is either in mempool or it isn't. Retry the proof submission if the first attempt was a timing issue.
84
+
85
+ This is the enterprise path — the client handles broadcasting, the server stays stateless.
86
+
87
+ ## Fee Delegation
88
+
89
+ For clients that don't hold BSV (zero-preload), a delegator service adds fee inputs:
90
+
91
+ 1. Client constructs partial tx (payment output only, no fee inputs)
92
+ 2. Client signs with `SIGHASH_ALL | ANYONECANPAY | FORKID` (`0xC1`)
93
+ 3. Client sends partial tx to the delegator
94
+ 4. Delegator appends fee inputs, signs only its fee inputs
95
+ 5. Delegator returns completed transaction
96
+ 6. Client proceeds with normal proof/payment flow
97
+
98
+ The delegator is between the client and the network — the server never talks to it. BSV transaction fees are negligible (1-50 sats), so fee delegation is a convenience, not a requirement.
data/docs/ecosystem.md ADDED
@@ -0,0 +1,83 @@
1
+ # Ecosystem
2
+
3
+ ## x402 Implementations
4
+
5
+ Three x402 ecosystems exist with different conventions. Our middleware supports all of them via the multi-gateway dispatch model.
6
+
7
+ ### Coinbase x402 v2 (broad ecosystem)
8
+
9
+ - **Headers**: `Payment-Required` / `Payment-Signature` / `Payment-Response`
10
+ - **Flow**: client signs authorisation → facilitator broadcasts (verify → serve → settle)
11
+ - **Replay protection**: chain-native (EIP-712 nonces, Solana blockhash)
12
+ - **Request binding**: resource URL only (no method/path/query hash)
13
+ - **Multi-chain**: `accepts` array for multi-chain/multi-scheme negotiation
14
+ - **Spec**: https://docs.x402.org
15
+ - **Our PR**: https://github.com/coinbase/x402/pull/1844 (BSV scheme spec)
16
+
17
+ ### Merkleworks x402 (BSV-specific)
18
+
19
+ - **Headers**: `X402-Challenge` / `X402-Proof`
20
+ - **Flow**: client broadcasts → server checks mempool (proof-of-payment)
21
+ - **Replay protection**: 1-sat nonce UTXO (single-spend at consensus layer)
22
+ - **Request binding**: strong (method, path, query, headers hash, body hash)
23
+ - **Spec**: https://github.com/ruidasilva/merkleworks-x402-spec
24
+ - **Reference impl**: https://github.com/merkleworks/x402-bsv
25
+
26
+ ### BRC-105 (BSV Association BRC)
27
+
28
+ - **Headers**: `x-bsv-payment-version` / `x-bsv-payment-satoshis-required` / `x-bsv-payment-derivation-prefix` / `x-bsv-payment`
29
+ - **Flow**: authenticated (BRC-103/104) payment with derivation-based unique addresses
30
+ - **Replay protection**: server-tracked derivation prefixes (server-side state)
31
+ - **Identity**: requires BRC-103 mutual authentication (but could work without — see below)
32
+ - **Spec**: https://github.com/bitcoin-sv/BRCs/blob/master/payments/0105.md
33
+
34
+ ## Header Namespace Reservations
35
+
36
+ | Namespace | Ecosystem |
37
+ |-----------|-----------|
38
+ | `Payment-*` | Coinbase v2 / our PayGateway |
39
+ | `X402-*` | Merkleworks / our ProofGateway |
40
+ | `x-bsv-*` | BRC-105 / BSV Association |
41
+
42
+ These namespaces must not overlap. When designing new headers or gateway types, check which namespace the target ecosystem uses.
43
+
44
+ ## Our Position
45
+
46
+ Our PayGateway implements the Coinbase v2 header spec with BSV as the settlement network. This makes BSV a first-class citizen in the broader x402 ecosystem — any Coinbase-compatible server or client can interoperate with us.
47
+
48
+ We also support merkleworks via a separate ProofGateway that uses the `X402-*` headers.
49
+
50
+ Our BRC105Gateway implements the BSV Association's native payment protocol using `x-bsv-*` headers, enabling interoperability with BRC-100 wallets and the broader BSV ecosystem tooling.
51
+
52
+ Coinbase will likely gatekeep BSV from their ecosystem — our conformance is about making it easy for others to integrate BSV as a supported network.
53
+
54
+ ## BRC-105: Standalone and Authenticated Modes
55
+
56
+ BRC-105 assumes BRC-103/104 mutual authentication, but `BRC105Gateway` supports both modes:
57
+
58
+ ### Standalone mode (no BRC-103)
59
+
60
+ The gateway advertises its identity key in the `x-bsv-payment-identity-key` challenge header. The client uses this for BRC-29 key derivation. Counterparty is `"anyone"` — anonymous payments similar to PayGateway but using BSV-native headers.
61
+
62
+ - No handshake required
63
+ - Transport security handled by TLS
64
+ - Replay protection via server-tracked derivation prefixes
65
+
66
+ ### Authenticated mode (with BRC-103 middleware)
67
+
68
+ When BRC-103 middleware is present upstream in the Rack stack, the gateway reads the client's authenticated identity key from `env['brc103.identity_key']` and uses it as the BRC-29 derivation counterparty. The identity key challenge header is omitted (the client already has the server's key from the BRC-103 handshake).
69
+
70
+ - Full BRC-105 compliance
71
+ - Payment bound to authenticated identity
72
+ - Stronger replay protection (session nonces + prefix tracking)
73
+
74
+ The gateway detects the mode automatically — no configuration change required. This allows composing `BRC103Middleware + BRC105Gateway` for the full authenticated flow, or using `BRC105Gateway` alone for the simpler anonymous path.
75
+
76
+ ## Related Projects
77
+
78
+ - **x402-rack** (this gem): server-side Rack middleware
79
+ - **bsv-x402** (npm): client-side fetch wrapper ([sgbett/bsv-x402](https://github.com/sgbett/bsv-x402))
80
+ - **bsv-sdk** (gem): BSV primitives — keys, transactions, scripts, ARC
81
+ - **bsv-wallet** (gem): BRC-100 wallet interface
82
+ - **BSV Browser**: BRC-100 wallet with `window.CWI` ([bsv-blockchain/bsv-browser](https://github.com/bsv-blockchain/bsv-browser))
83
+ - **402index.io**: x402 endpoint aggregator with payment flow examples