---
status: reconciled-partial
coverage_depth: deep-for-shipped-core
last_reconciled: 2026-07-18
specs:
  - apps/oshun/web/e2e/billing-crypto-paywall.spec.ts
  - apps/oshun/bff/src/__tests__/payments-crypto-route.test.ts
  - apps/oshun/bff/src/payments/settlement-route.test.ts
source: WALKTHROUGH/results/external-dependencies/README.md
---

# Dependency result: Crypto merchant settlement

- **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.

```mermaid
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

- [External-dependency index](./README.md)
- [Payments composition root](../../../apps/oshun/bff/src/payments/payments-composition.ts)
- [E2E-only provisioner](../../../apps/oshun/bff/src/payments/e2e-payments-runtime.ts)
- [Quote route](../../../apps/oshun/bff/src/routes/domain-stubs.ts)
- [Invoice ledger](../../../apps/oshun/bff/src/payments/invoice-store.ts)
- [Settlement receiver](../../../apps/oshun/bff/src/payments/settlement-route.ts)
- [Crypto paywall browser suite](../../../apps/oshun/web/e2e/billing-crypto-paywall.spec.ts)
- [Settlement service suite](../../../apps/oshun/bff/src/payments/settlement-route.test.ts)

## Cross-references

- [Sign-up and pay with crypto journey](../../journeys/sign-up-and-pay-crypto.md)
- [Billing view](../../customer/10-billing/billing.md)
- [AAA entitlement journey](../../journeys/aaa-upgrade-entitlement-bounce.md)
- [Crisis-aware tone result](../crisis-aware-tone-policy.md)
- [External-dependency convention](./README.md)

## 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?
