- Opened: 2026-05-29 when the quote route returned a synthetic burn address and there was no settlement receiver or entitlement reconciliation.
- Reconciled: 2026-07-18 against the current composition root, quote route, durable invoice ledger, signed settlement receiver, entitlement grant, unit suites, and crypto paywall browser suite. This was a source reconciliation, not a live merchant or chain walk.
- Verdict: partial — the unsafe stub is gone and the in-repository quote-to-settlement core is substantial: unconfigured production fails closed without issuing an address; a bound runtime can provision a unique target, persist an invoice, verify a raw-byte HMAC settlement, mint a signed receipt, and price-bind an entitlement grant. A production provisioner, merchant or wallet credentials, and chain watcher are still deploy-bound and absent from the default server composition.
- Primary specs:
billing-crypto-paywall.spec.ts,payments-crypto-route.test.ts, andsettlement-route.test.ts.
Result at a glance#
| Evidence lane | Current result | Authority limit |
|---|---|---|
| Unconfigured safety | Quote returns 503 and no receiving address; payable methods are inactive | Availability, not a completed payment rail |
| Quote issuance | Bound provisioner supplies exact chain amount and unique target; invoice is recorded | Unit/E2E doubles, not a live merchant or wallet |
| Invoice ledger | Purchaser-scoped reads, operator view, retained paywall DTO, snapshot durability | Snapshot store, not an independently reconciled merchant ledger |
| Settlement receiver | Raw-byte HMAC, timestamp bound, replay guards, block facts, and signed receipt | Caller is an assumed deploy-bound watcher |
| Entitlement grant | Authenticated, book-priced invoices can grant; underpriced/legacy invoices cannot | Test identity and in-app plan store, not a live paid chain transaction |
| Browser proof | Harness issues invoice, renders QR/address, settles, reads plan/ledger, hides address | E2E provisioner and signed test webhook; no public-chain confirmation |
Evidence map#
Solid edges are implemented and automated with injected test capabilities. Dashed edges are the production integrations the repository intentionally does not fabricate.
flowchart LR
A[Customer quote request] --> B{Runtime bound}
B -->|no| C[503 and no address]
B -->|yes| D[Provision unique target]
D --> E[Durable pending invoice]
E --> F[Paywall QR and copy]
G[Chain watcher] -. deploy-bound .-> H[Signed settlement POST]
H --> I[Confirm invoice and signed receipt]
I --> J{Book price covered}
J -->|yes| K[Grant plan]
J -->|no| L[Withhold and support flag]
M[Live merchant or wallet] -. not bound by default .-> D
Proven observations#
The route now fails safely and composes real capabilities#
resolvePaymentsRuntime()returns a runtime only when both an Ed25519 receipt signer and an injected invoice-target provisioner exist. The default server injects only the explicitly gated non-production E2E provisioner, so ordinary production composition remains null and/v1/payments/crypto/quotereturns 503 without a receiving target.- A bound runtime delegates rate, chain amount, and unique receiving target to the provisioner. The BFF applies the server-side plan price book, rejects client price/currency drift, applies disclosure gates, and records the full pending invoice after provisioning.
- The invoice store hydrates and writes through the repository durable snapshot seam. Member ledger reads are purchaser-scoped; operators retain a full view.
Settlement and browser behavior are deeply exercised#
/v1/payments/crypto/settlementsverifies HMAC-SHA256 over the exact received bytes plus a timestamp, requires block hash and height, rejects stale or malformed requests, and uses both an in-process reference guard and the persisted pending-to-confirmed state as idempotency barriers.- Confirmation records the transaction and inclusion facts, mints an Ed25519-signed receipt, and grants a stated plan only when the stored invoice covers the canonical price book. Underpriced or legacy unpriced plan invoices settle without granting and receive a support flag.
- The browser suite drives a test-issued invoice through the paywall, QR/address display, signed settlement, plan readback, purchaser ledger, by-id status, stale-address removal, and idempotent redelivery. Failure cases preserve the pending invoice and free plan.
Boundaries and gaps#
- A safe 503 is not merchant availability. The default production server supplies no BTCPay, OpenNode, exchange, or wallet provisioner, so it cannot issue a payable invoice without deploy work.
- An injected provisioner is not a live provider. Unit and browser suites use deterministic doubles. They do not prove KYB, credentials, live exchange rates, unique-address custody, network fees, expiration, refund, or provider outage behavior.
- A settlement receiver is not a chain watcher. The route trusts an authenticated deploy-bound watcher to send inclusion facts; no repository service scans BTC, Base, or another network and calls it in production.
- Signed inclusion facts are not independent chain verification. HMAC authenticates the watcher and the receipt attests what OSHUN recorded; neither demonstrates confirmations against an independent node in this result.
- Snapshot durability is not financial-ledger reconciliation. The in-app ledger survives configured restarts but no merchant statement, chain index, double-spend/reorg policy, or accounting export is reconciled here.
- Harness settlement is not a real-money walk. The E2E provisioner and webhook secret deliberately exercise the product core without transferring funds or validating a production deployment.
Re-run evidence#
The shipped core is covered at the service and browser layers:
bash
pnpm exec vitest run \
apps/oshun/bff/src/__tests__/payments-crypto-route.test.ts \
apps/oshun/bff/src/payments/settlement-route.test.ts
PW_BROWSER_CHANNEL=chrome pnpm exec playwright test \
-c apps/oshun/web/playwright.config.ts \
apps/oshun/web/e2e/billing-crypto-paywall.spec.ts \
--workers=1
A green run proves the in-repository core with injected test capabilities. It must not be represented as live merchant onboarding, production chain watching, or a real-money settlement.
Source trail#
- External-dependency index
- Payments composition root
- E2E-only provisioner
- Quote route
- Invoice ledger
- Settlement receiver
- Crypto paywall browser suite
- Settlement service suite
Cross-references#
- Sign-up and pay with crypto journey
- Billing view
- AAA entitlement journey
- Crisis-aware tone result
- External-dependency convention
Open questions#
- Which production provisioners serve each asset, and where are their credentials, rate-quality rules, target uniqueness, and health gates bound?
- Which chain-watcher deployment supplies inclusion facts, handles confirmations and reorgs, and retries until the durable receipt is recorded?
- What reconciliation compares the OSHUN invoice ledger with provider and chain records, and how are discrepancies surfaced to operators?
- How are expiration, late settlement, refunds, under/overpayment, wrong-chain transfers, and support recovery modeled end to end?
- What production canary proves quote, payment, watcher, receipt, entitlement, and customer readback without exposing real funds to an unsafe fallback?