Proof and operations
Infrastructure
What runs where, which component is the source of truth, and what has to be true before mainnet.
Components
| Component | Role |
|---|---|
| Facilitator API | Verifies and settles x402 payments, submits transactions through the relayer, and reports capabilities and health. |
| Merchant paywall and tool service | Issues 402 terms, runs capabilities, signs receipts, serves resolve, catalogue and discovery documents. |
| Reconciler | Moves operations with unknown outcomes to a proven state using chain evidence. |
| Indexer | Follows chain events relevant to Tollex operations. |
| Discovery worker | Ingests and probes external catalogues. |
| Analytics API and console | Read-only views over the database. Every number is computed at request time. |
PostgreSQL is the system of record: operations, state transitions, authorizations, settlements, receipts, budgets and intent resolutions. Payment state is written before money moves.
Chain access
Production deployments use at least two independent RPC providers, and a transaction receipt is only accepted when providers agree. A single provider returning an invented receipt is treated as a fault, not as proof.
Signing keys
The relayer key can live in AWS KMS, Google Cloud KMS, a Vault Transit backend or a remote signer such as Web3Signer. A local key is refused in production mode. Receipt keys and agent keys are separate from the relayer key.
The mainnet gate
Mainnet writes require TOLLEX_MAINNET_WRITES=enabled. No shipped configuration sets it, nothing falls back from testnet to mainnet, and the gate is covered by tests, including misconfiguration cases. Every new path, resolve and do() included, goes through the same gate.
Tollex is verified on Robinhood Chain testnet. It is ready for an external audit, which has not happened yet. Mainnet stays read-only until the audit and the remaining operational gates are complete.
Observability
Prometheus metrics cover verification and settlement latency, reconciliation age, relayer balance, receipt failures, tool calls and routing:
tollex_intent_resolve_total{outcome} selected | no_candidate | invalid
tollex_intent_resolve_duration_seconds
tollex_intent_candidate_count{stage} evaluated | eligible
tollex_intent_candidate_rejected_total{reason} one label per rejection code
tollex_intent_provider_selected_total{provider}
tollex_intent_resolve_no_candidate_total
tollex_intent_do_execution_total{outcome}
tollex_intent_do_execution_failure_total{reason}
tollex_intent_routing_price_atomic
tollex_intent_routing_observed_p95_seconds
tollex_intent_routing_success_rate
tollex_external_candidate_total{stage} evaluated | eligible
tollex_external_selected_total
tollex_external_execution_total{outcome} paid_delivered | paid_not_delivered | not_charged | ...
tollex_external_execution_failed_total{reason}
tollex_external_requirements_changed_total
tollex_external_settlement_pendingLabels are bounded: reason codes are a fixed set, and providers come from the registry. External merchants share one provider label, so a merchant’s host never becomes a label.