V1 Web PWA · Walk result

Dependency result: Crypto merchant settlement

A dated evidence record for V1 Web PWA: observed behavior, current source reconciliation, automation evidence, and explicit proof limits.

verdict: partial· date unknown
8sections5 minread1table

On this page
  • 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, and settlement-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/quote returns 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/settlements verifies 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#

Cross-references#

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?