<!-- Generated raw Markdown for /concepts/architecture; product pin 638fa1e9ca7face19a442cef43754f0d627c7705. -->

SubEtha's runtime is three parties talking over plain HTTP, plus the local
zERC20 stack that only one of them ever touches. This page maps the parties,
the HTTP surfaces between them, and the trust boundaries — who holds which
keys and who can do what. The wire format itself is the
[wire protocol reference](/reference/protocol/); the lifecycle semantics are
[x402 v2 on SubEtha](/concepts/x402-v2/) and
[Accepted vs finalized](/concepts/accepted-vs-finalized/).

## The three parties

```
payer (AI agent / script)
   │  x402 v2 over HTTP: request → 402 offer → paying request → resource
   ▼
provider (resource server, official x402 middleware + SubEtha scheme plugin)
   │  facilitator HTTP API: /supported /challenge /verify /settle
   ▼
facilitator (settlement daemon)
   │  RPC + indexer + prover — the only party that touches the chain
   ▼
local zERC20 stack (anvil, deployed contracts, indexer, decider)  →  treasury
```

- **The payer** requests the resource and pays. It sees only what the 402
  offer shows it: token, network, quoted amount, expiry, and a one-time burn
  address as `payTo`. It is never shown the provider's real payout
  destination.
- **The provider** serves the HTTP resource behind a paywall. It runs the
  official x402 middleware with the SubEtha scheme plugin and delegates every
  payment question to the facilitator.
- **The facilitator** derives the one-time burn addresses, verifies and
  settles payments, and later drives finalization (the proof-gated mint). It
  is the only component that talks to the chain, the indexer, or the prover.

## The HTTP boundary

Everything between parties is HTTP — there is no shared database, queue, or
SDK linkage across party lines.

**Payer ↔ provider** is unmodified x402 v2: the `PAYMENT-REQUIRED` header on
the 402 response (the offer), `PAYMENT-SIGNATURE` on the paying request (the
payment), and `PAYMENT-RESPONSE` on the served response (the settlement
result). SubEtha adds no headers and provides no x402 v1 fallback.

**Provider ↔ facilitator** is the standard x402 facilitator API plus one
SubEtha extension:

| endpoint | why the provider calls it |
|---|---|
| `GET /supported` | at initialization — the middleware hard-fails unless the facilitator advertises the `subetha-zerc20` kind |
| `POST /challenge` | per unpaid 402 — a burn address can only be derived by the facilitator, so a provider cannot mint its own offer the way vanilla x402 sellers do |
| `POST /verify` | on a paying request — a read-only, point-in-time check |
| `POST /settle` | after the resource handler ran — executes the burn-confirmation path; success means `accepted` |

The facilitator treats the requirements echoed in these calls as untrusted
and compares them against its own challenge record, rejecting any mismatch.

## Trust boundaries: who holds what

| party | holds | can |
|---|---|---|
| payer | its own EOA key | sign or broadcast a burn to the offered `payTo`; nothing else |
| provider | **no keys** in the shipped configuration — not even a payout EOA's | serve or withhold the resource; it never touches the chain or the zERC20 SDK |
| facilitator | `SUBETHA_TREASURY_PK`, `SUBETHA_RELAYER_PK`, the burn-address derivation seed, optional `SUBETHA_ADMIN_TOKEN` | derive offers, broadcast permit burns, submit proof-gated mints, sweep fees |

Three consequences of that split:

- **The payout destination lives facilitator-side.** The provider's route
  config carries no payout address or secret; the treasury (or the FeeSplit
  contract) is named in the facilitator's configuration. A compromised
  provider process therefore leaks no settlement keys.
- **The BUSL boundary is confined to the facilitator.** All use of
  `@zerc20/sdk` (BUSL-1.1) and its Node/wasm specifics lives inside the
  facilitator's settlement backend. Payer and provider integrate through
  Apache-2.0 packages and plain HTTP.
- **The facilitator is fully trusted for settlement.** It sees every payment,
  derives every burn address, and controls when finalization runs. What that
  trust means in practice — and what failure looks like at each boundary — is
  [Trust & Limits](/trust/).

## The chain-side machinery

The facilitator settles against the **official zERC20 stack running locally**:
anvil as the chain, the deployed official contracts, the indexer, and the
decider/prover. That stack is a prerequisite the product repository documents
(build it per
[`docs/BUILDING-THE-STACK.md`](https://github.com/peaceandwhisky/SubEtha/blob/638fa1e9ca7face19a442cef43754f0d627c7705/docs/BUILDING-THE-STACK.md),
run it per
[`docs/RUNNING-THE-STACK.md`](https://github.com/peaceandwhisky/SubEtha/blob/638fa1e9ca7face19a442cef43754f0d627c7705/docs/RUNNING-THE-STACK.md));
it is not vendored into SubEtha and not documented further on this site.

One SubEtha-authored contract participates: `PermitBurner` (Apache-2.0), the
helper that makes the gasless permit path atomic — it grants the allowance
from the payer's EIP-2612 signature and executes the burn transfer in a
single transaction.
