walras

FACTS.md — walras (Stellar x402 facilitator + Bazaar)

Single source of truth. Rules:

Pinned spec commit: x402-foundation/x402 @ 17fc9890ade45a570a019352a3573391ad5d1e1f (main, committed 2026-08-01T14:16:23+02:00; cloned to /workspaces/x402 on 2026-08-02. All specs/… and typescript/… paths below are at that SHA.)

RFP source text: docs/rfp.md (verbatim, captured 2026-08-02). Evidence transcripts: docs/EVIDENCE.md. Divergence log: docs/DECISIONS.md.


Verified — carried forward from 2026-07-31 (web-sourced)

ID Claim Status Date Source
F-001 @x402/stellar exists on npm; Apache-2.0. Version superseded — see F-040. VERIFIED 2026-07-31 npmjs.com/package/@x402/stellar
F-002 Protocol repo is github.com/x402-foundation/x402 (migrated from coinbase/x402) VERIFIED 2026-07-31 repo README; npm package links
F-003 Package provides Client / Facilitator / Server components; ExactStellarScheme; createEd25519Signer implements SEP-43 SignAuthEntry + SignTransaction VERIFIED 2026-07-31 npm README; re-confirmed at SHA (F-030)
F-004 Networks: stellar:testnet (default RPC https://soroban-testnet.stellar.org), stellar:pubnet (custom RPC URL required), stellar:* wildcard; CAIP-2; x402 v2 VERIFIED 2026-07-31 npm README; re-confirmed at SHA (F-041)
F-005 @x402/stellar implements the exact scheme only today → the upto Stellar gap in the RFP is real VERIFIED 2026-07-31 npm README; re-confirmed: only specs/schemes/upto/scheme_upto_{evm,svm}.md exist at SHA — no Stellar variant
F-006 Facilitators currently always sponsor fees; areFeesSponsored: true VERIFIED 2026-07-31 npm README; re-confirmed live (F-025) and in source (F-031)
F-007 Validity is ledger-based, ~12 ledgers ≈ 60 s. Derivation now pinned — see F-028. VERIFIED 2026-07-31 npm README
F-008 Any SEP-41 token supported; USDC default, 7 decimals; amounts in base units VERIFIED 2026-07-31 npm README; confirmed on-chain (F-036, F-038)
F-009 Bazaar is codified as an official v2 extension in the reference SDK VERIFIED 2026-07-31 docs.cdp.coinbase.com/x402/bazaar; spec at SHA
F-010 Cataloging is automatic after successful settle; no separate registration step. CDP behavior — NOT spec-mandated. See F-023. VERIFIED (CDP only) 2026-07-31 docs.cdp.coinbase.com/x402/bazaar
F-011 Cataloging outcomes reported via EXTENSION-RESPONSES header VERIFIED 2026-07-31 spec at SHA (F-024); SDK source (F-039)
F-012 CDP prunes resources with no settlements for 30 days VERIFIED (CDP behavior, not spec) 2026-07-31 docs.cdp.coinbase.com/x402/bazaar
F-013 CDP's /discovery/search has no pagination. Confirmed as ecosystem-wide — the reference SDK impl also returns pagination: null unconditionally (F-027). VERIFIED 2026-07-31 docs.cdp.coinbase.com; e2e/facilitators/typescript/bazaar.ts
F-014 CDP exposes the Bazaar to agents via MCP with tools shaped like search_resources / proxy_tool_call VERIFIED 2026-07-31 docs.cdp.coinbase.com/x402/bazaar
F-015 OpenZeppelin Relayer is AGPL-3.0; @openzeppelin/relayer-sdk AGPL-3.0-or-later → excluded per RFP 3.6 VERIFIED 2026-07-31 github.com/OpenZeppelin/openzeppelin-relayer; npm
F-016 SDF is a Premier member of the x402 Foundation with a Governing Board seat; Foundation launch 2026-07-14 VERIFIED 2026-07-31 stellar.org/x402; RFP §2 corroborates
F-017 x402.org facilitator supports stellar:testnet with sponsored fees VERIFIED 2026-07-31 confirmed live (F-025)
F-018 stellar/x402-stellar repo carries SDF tools, examples, reference facilitator example VERIFIED 2026-07-31 developers.stellar.org; RFP appendix
F-019 Freighter browser extension supports x402; Freighter Mobile does not yet VERIFIED 2026-07-31 developers.stellar.org x402 docs
F-020 SDK family includes @x402/extensions and @x402/mcp VERIFIED 2026-07-31 confirmed on npm (F-040)
F-021 @x402/extensions provides bazaarResourceServerExtension and withBazaar VERIFIED 2026-07-31 source at SHA (F-032)
F-022 Built on Stellar facilitator is built on OZ Relayer + x402 plugin (AGPL-excluded) VERIFIED 2026-07-31 developers.stellar.org

Context facts (submission, not build)

ID Claim Status Date Source
C-001 SCF FAQ: generally one project at a time per submitter VERIFIED 2026-07-31 SCF Handbook FAQ
C-002 Repeat Build applicants must show significant progress on prior project; reviewers assess only submission content VERIFIED 2026-07-31 SCF Handbook
C-003 Round deadline arrives in the SCF invitation email VERIFIED (imprecise) 2026-07-31 SCF Handbook
C-004 RFP Track: submissions reviewed by 2 reviewers from the quarter's Category Delegate Panel; third breaks ties. Scope may be limited if reasoning is articulated. Q3 RFPs opened 2026-07-23 for SCF #45. VERIFIED 2026-08-02 docs/rfp.md Part A

Verified — Session 0, from pinned spec / source / live measurement

Bazaar extension (Q-001) — specs/extensions/bazaar.md @ SHA

ID Claim Status Date Source
F-023 The spec does not require cataloging to be gated on settlement. Facilitator Behavior says only: (1) validate info against schema, (2) extract. "How a facilitator stores, indexes, and exposes discovered resources is an implementation detail." Settle-gating is our deliberate choice, not conformance. VERIFIED 2026-08-02 specs/extensions/bazaar.md §Facilitator Behavior
F-024 EXTENSION-RESPONSES is base64-encoded JSON keyed by extension name. bazaar.status"success" | "processing" | "rejected" (required); bazaar.rejectedReason (optional string, human-readable, only when rejected). Facilitator MAY append it — it is not mandatory. VERIFIED 2026-08-02 specs/extensions/bazaar.md §Verify and Settlement Response Header
F-025 /discovery/resources filters are seven, not six: type, payTo, scheme, network, extensions, limit, offset. RFP 3.2 omits scheme. Defaults from v2 spec §8.1: limit = 20 (range 1–100), offset = 0. VERIFIED 2026-08-02 specs/extensions/bazaar.md; specs/x402-specification-v2.md §8.1
F-026 /discovery/search query parameter is named query, not q. Required. Other params: type, payTo, scheme, network, extensions, limit, cursor. limit and cursor are explicitly advisory — "facilitator may return fewer or ignore". VERIFIED 2026-08-02 specs/extensions/bazaar.md; extensions/src/bazaar/facilitatorClient.ts L282-304
F-027 List and search return different array field names. List → items; search → resources. Confirmed in three places: TS types DiscoveryResourcesResponse.items vs SearchDiscoveryResourcesResponse.resources; the reference e2e catalog; v2 spec §8.1 example. bazaar.md's prose "mirrors the list endpoint with a resources array" is loose wording, not a third shape. VERIFIED 2026-08-02 extensions/src/bazaar/facilitatorClient.ts L126-159; e2e/facilitators/typescript/bazaar.ts L25-67
F-028 Search response fields: partialResults?: boolean ("true when additional matches were truncated"); pagination?: {limit: number, cursor: string | null} | null. Note search pagination has no offset/total — unlike list pagination {limit, offset, total}. VERIFIED 2026-08-02 specs/extensions/bazaar.md; facilitatorClient.ts L145-159
F-029 MCP resources are keyed on the tuple (resource.url, input.toolName) — facilitators MUST use both because MCP multiplexes tools over one endpoint. VERIFIED 2026-08-02 specs/extensions/bazaar.md §MCP Tools note
F-030 routeTemplate validation: non-empty; starts /; matches ^/[a-zA-Z0-9_/:.\-~%]+$; no ..; no ://. Percent-decoding MUST precede the .. and :// checks. Failure = discard field and fall back to concrete URL path (soft-drop, not rejection). Shipped as isValidRouteTemplate. VERIFIED 2026-08-02 specs/extensions/bazaar.md §routeTemplate Validation Rules; extensions/src/bazaar/facilitator.ts L31-66
F-031 Soft-drop service metadata rules apply to resource.serviceName / tags / iconUrl (not to the discovery info block). serviceName: printable ASCII U+0020–U+007E, ≤32 chars. tags: ≤5 entries, each ≤32 printable-ASCII chars, deduped case-insensitively, first occurrence wins. iconUrl: ≤2048 chars, absolute http(s) only, no userinfo, IDN-normalized (UTS #46), rejects IP literals / loopback set / all-digit / hex hostnames. Percent-decode the host before IP and loopback checks. VERIFIED 2026-08-02 specs/extensions/bazaar.md §Validation Rules; extensions/src/bazaar/facilitator.ts L83-283
F-032 Clients echo the bazaar extension from PaymentRequired into PaymentPayload. If omitted, no cataloging occurs — the seller cannot force a listing. VERIFIED 2026-08-02 specs/extensions/bazaar.md §Client Behavior

Exact-Stellar scheme (Q-002) — specs/schemes/exact/scheme_exact_stellar.md @ SHA

ID Claim Status Date Source
F-033 payload is exactly {"transaction": "<base64 XDR>"} — a Stellar transaction with a single invokeHostFunction op calling transfer(from, to, amount) plus signed auth entries. Scope is SEP-41 Soroban tokens only; classic Stellar assets are not supported. VERIFIED 2026-08-02 spec §PaymentPayload payload Field, §Summary NOTE
F-034 Auth-entry expiry derivation: ledgerTimeout = ceil(maxTimeoutSeconds / estimatedLedgerSeconds), using the live network estimate where available, fallback 5 s. With the default maxTimeoutSeconds: 60 this yields 12 ledgers — the origin of the "~12 ledgers ≈ 60 s" figure in F-007. VERIFIED 2026-08-02 spec §Protocol Flow step 4, §Authorization Entries
F-035 Facilitator verification MUST list has five groups: protocol (version/scheme/network), transaction structure (1 op, contract == asset, fn transfer w/ 3 args, arg1 == payTo, arg2 == amount as i128), auth entries (sorobanCredentialsAddress only, no subInvocations, all required signers signed, expiry bound), facilitator safety (facilitator must not be tx source, op source, from, or appear in any auth entry; simulation must show only the expected balance changes), and simulation (must succeed and emit events confirming the exact amount). VERIFIED 2026-08-02 spec §Facilitator Verification Rules (MUST)
F-036 /settle MUST perform full verification independently and MUST NOT assume prior verification. The package already honours this — settle() calls _verify() as its Step 1. Our wrapper must therefore NOT re-verify. VERIFIED 2026-08-02 spec §Protocol Flow step 10 NOTE; mechanisms/stellar/src/exact/facilitator/scheme.ts L208
F-037 Fee rules: facilitator MUST derive the settlement fee from a fresh settle-time simulation (simulationResourceFee + inclusionBuffer, buffer ≥ 100 stroops), refresh Soroban footprint/resourceFee from that simulation, and fully override the client's fee bid. Optional maxTransactionFeeStroops ceiling, default 50 000 stroops, rejects with invalid_exact_stellar_payload_fee_exceeds_maximum. VERIFIED 2026-08-02 spec §Transaction Fees
F-038 SettlementResponse = {success, transaction, network, payer} where transaction is the 64-char hex tx hash and payer is the client's address (never the facilitator's). VERIFIED 2026-08-02 spec §Phase 3
F-039 The spec's MUST list contains no explicit replay check. Replay resistance is structural: a reused Soroban auth-entry nonce makes re-simulation fail, and simulation success is itself a MUST. The package likewise has no explicit replay branch. RFP 3.1 demands "not replayed", so this must be stated as structural and demonstrated empirically, not claimed as a coded check. VERIFIED 2026-08-02 spec §Facilitator Verification Rules; scheme.ts L493-504 (no replay branch)

Facilitator surface & /supported (Q-003, Q-005)

ID Claim Status Date Source
F-040 /supported returns {kinds[], extensions[], signers{}}all three required. Each kind: {x402Version, scheme, network, extra?}. signers maps CAIP-2 patterns (stellar:*) to public addresses. VERIFIED 2026-08-02 specs/x402-specification-v2.md §7.3, §7.3.1
F-041 Live capture of https://x402.org/facilitator/supported returns for Stellar: {"x402Version":2,"scheme":"exact","network":"stellar:testnet","extra":{"areFeesSponsored":true}}, and signers["stellar:*"] = ["GC6CSXBV4C6RL3HEDTW57KXYXSSXKAWKGYDEOSATXM3XNKXSR2VRYN3K","GC5OLUZ4WANPN6VT7YGTK2SRMZG762KOVKJXHWIO4K57UBASO2FMNRET"] (two signers). No stellar:pubnet kind is advertised. VERIFIED 2026-08-02 evidence §S0-2
F-042 The x402.org facilitator advertises extensions: ["builder-code","eip2612GasSponsoring","erc20ApprovalGasSponsoring"]bazaar is absent. The public conformance baseline does not advertise Bazaar support at all. VERIFIED 2026-08-02 evidence §S0-2
F-043 areFeesSponsored is not Stellar-only: x402.org advertises xrpl:1 with extra.areFeesSponsored: false, confirming it as a cross-chain field with a meaningful false case. VERIFIED 2026-08-02 evidence §S0-2
F-044 Wrap target: class ExactStellarScheme implements SchemeNetworkFacilitator, imported from @x402/stellar/exact/facilitator. Constructor (signers: FacilitatorStellarSigner[], {rpcConfig?, areFeesSponsored=true, maxTransactionFeeStroops=50_000, selectSigner=roundRobin, feeBumpSigner?}). Methods: verify(), settle(), getExtra(network){areFeesSponsored}, getSigners(network). Package exports: ., ./exact/client, ./exact/server, ./exact/facilitator. VERIFIED 2026-08-02 mechanisms/stellar/src/exact/facilitator/scheme.ts L85-174; package.json exports
F-045 The package performs all of the spec's verification MUSTs itself, emitting 37 distinct machine-readable reason codes (30 on the verify path, 7 on the settle path; enumerated in DECISIONS D-007). Our wrapper adds zero payment validation — its jobs are HTTP surface, config, caller auth, and the discovery hook. VERIFIED 2026-08-02 scheme.ts L379-556, L610-804
F-046 The package tolerates auth-entry expiry 2 ledgers beyond the spec's strict bound (SIGNATURE_EXPIRATION_LEDGER_TOLERANCE = 2, for RPC skew). The spec says MUST NOT exceed currentLedger + ceil(...). This is an implementation deviation we inherit by wrapping. VERIFIED 2026-08-02 scheme.ts L37, L769
F-047 Settle supports an optional feeBumpSigner that wraps the inner transaction in a FeeBumpTransaction, decoupling fee payment from sequence-number management — i.e. the throughput answer to RFP 3.5 is already in the package. VERIFIED 2026-08-02 scheme.ts L106-108, L287-323

Bazaar facilitator-side helpers (Q-006)

ID Claim Status Date Source
F-048 @x402/extensions DOES ship facilitator-side cataloging helpers — contradicting the pre-build plan's expectation (Q-006 "Expected: our build"). Exported from @x402/extensions/bazaar: extractDiscoveryInfo, extractDiscoveryInfoFromExtension, validateAndExtract, validateDiscoveryExtension (Ajv 2020-12 against the supplied schema), validateDiscoveryExtensionSpec (protocol invariants), isValidRouteTemplate, isValidServiceName, sanitizeTags, isValidIconUrl, sanitizeResourceServiceMetadata. VERIFIED 2026-08-02 extensions/src/bazaar/index.ts L108-127
F-049 What remains our build: persistence, indexing, the two discovery HTTP endpoints, ranking, retention, and the DiscoveredResourceDiscoveryResource wire mapping. The package stops at extraction; it never stores or serves. VERIFIED 2026-08-02 extensions/src/bazaar/facilitator.ts (no storage); spec §Facilitator Behavior
F-050 Two distinct types with confusingly similar names. DiscoveredResource (extraction output) = {resourceUrl, description?, mimeType?, serviceName?, tags?, iconUrl?, method?|toolName, routeTemplate?, x402Version, discoveryInfo, extensions?}. DiscoveryResource (catalog wire shape) = {resource, type, x402Version, accepts[], lastUpdated, description?, mimeType?, serviceName?, tags?, iconUrl?, extensions?}. The mapping between them is unimplemented in the package and is ours. VERIFIED 2026-08-02 bazaar/http/types.ts, bazaar/mcp/types.ts, bazaar/facilitatorClient.ts L98-121
F-051 extractDiscoveryInfo canonicalizes the catalog URL as ${origin}${routeTemplate} when a valid routeTemplate is present, else ${origin}${pathname} — query string and fragment are stripped. On schema-validation failure it console.warns and returns null (soft-drop, never throws). VERIFIED 2026-08-02 extensions/src/bazaar/facilitator.ts L504-538

Toolchain, assets, fees (Q-004, Q-007, Q-008, Q-010, Q-012, Q-013)

ID Claim Status Date Source
F-052 Testnet USDC SAC contract ID is CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA, wrapping classic asset USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5, decimals() == 7. Verified four independent ways: spec example, package constant USDC_TESTNET_ADDRESS, on-chain ledger entry (executable == contractExecutableStellarAsset, METADATA storage), and cryptographic re-derivation Asset("USDC", issuer).contractId(TESTNET) round-tripping to the same ID. VERIFIED 2026-08-02 evidence §S0-3
F-053 Mainnet USDC SAC constant is CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75 (package constant; not independently verified on pubnet — out of pre-build scope). VERIFIED (source only) 2026-08-02 mechanisms/stellar/src/constants.ts L29
F-054 Measured settlement fee on stellar:testnet: 23 073 stroops = 0.0023073 XLM, observed repeatedly across the x402.org facilitator's settlements (a second cluster at 20 654 stroops = 0.0020654 XLM). The RFP's "about 0.0023 XLM" (§2) is confirmed to two significant figures by live measurement. Observed max_fee 33 253 — only ~1.5× headroom under the 50 000-stroop default ceiling (F-037). VERIFIED 2026-08-02 evidence §S0-4
F-055 The x402.org Stellar facilitator settles using a fee-bump transaction with a separate fee account (source_account = GC6CSXBV…, fee_account = GC5OLUZ4…), i.e. it uses the package's feeBumpSigner path in production. VERIFIED 2026-08-02 evidence §S0-4
F-056 e2e suite lives at e2e/, run with pnpm install:all then pnpm test (interactive selector) or pnpm test --min. Stellar env vars: SERVER_STELLAR_ADDRESS, CLIENT_STELLAR_PRIVATE_KEY, FACILITATOR_STELLAR_PRIVATE_KEY; facilitator process also reads STELLAR_PRIVATE_KEY, STELLAR_NETWORK (default stellar:testnet), STELLAR_RPC_URL. Requires Node ≥ 22. Setup path: Stellar Lab keypair + Friendbot → USDC trustline via lab.stellar.org/account/fund → Circle faucet (faucet.circle.com, select Stellar) for testnet USDC. VERIFIED 2026-08-02 e2e/README.md L120-226; e2e/package.json
F-057 Wire header names: request X-PAYMENT; payment response X-PAYMENT-RESPONSE SUPERSEDED by F-065 — these are the v1 names only; the SDK switches on x402Version and Session 0 read the v1 branch. EXTENSION-RESPONSES (facilitator→server) remains correct. SUPERSEDED 2026-08-02 D-018; F-065
F-058 Toolchain pinned: Node v24.14.0 (local) — but @x402/stellar and the e2e suite both declare engines.node >= 22; pnpm 10.32.1; npm 11.9.0; git 2.53.0. All @x402/* packages at 2.20.0, Apache-2.0. VERIFIED 2026-08-02 G0.1 capture; npm view; evidence §S0-1
F-059 @x402/stellar@2.20.0 requires @stellar/stellar-sdk: ^16.0.1 and @x402/core: ~2.20.0. Pinning @stellar/stellar-sdk at ^14 produces a duplicate SDK in the tree (14.6.1 + 16.2.0) and the settle path's fee arithmetic is written against v16 semantics. We must pin ^16. VERIFIED 2026-08-02 node_modules/@x402/stellar/package.json; evidence §S0-5; scheme.ts L253 comment
F-060 Q-010 license scan PASS. 294 distinct packages across the full planned dependency set: 249 MIT, 17 Apache-2.0, 14 ISC, 8 BSD-3-Clause, 2 BSD-2-Clause, 3 permissive dual/multi, 1 Unlicense. Zero AGPL/SSPL/OSL/EUPL/CPAL/RPL. Zero GPL/LGPL/MPL/CDDL/EPL. Zero undeclared. VERIFIED 2026-08-02 evidence §S0-5
F-061 Package version drift is fast and real: @x402/* moved 2.17.0 → 2.20.0 in the two days between the 2026-07-31 fact-check and 2026-08-02. The pinned spec SHA is dated 2026-08-01, one day before this session. The RFP's "drift, not inability, is the failure mode" (§4) is empirically supported. VERIFIED 2026-08-02 F-001 vs F-058

Session 1 — from package source and the published artifact

ID Claim Status Date Source
F-062 gatherAuthEntrySignatureStatus classifies an auth entry as signed purely by testing that its signature ScVal is not scvVoid — it performs no cryptographic verification. A forged or corrupted signature is therefore invisible to every check @x402/stellar makes on its own, and is caught only by the Soroban host during simulation. This is why "simulation MUST succeed" (F-035) is load-bearing rather than defence-in-depth: it is the sole control against a forged authorization. VERIFIED 2026-08-02 mechanisms/stellar/src/shared.ts L117-126 @ SHA; demonstrated S1-4
F-063 The 37 reason codes of F-045 are present in the published npm artifact of @x402/stellar@2.20.0 (dist/esm/exact/facilitator/index.mjs), not only in the source tree S0-6 read. The enumeration is asserted against the installed bundle by packages/facilitator/test/errors.test.ts, so an upstream rename breaks the build rather than degrading a rejection reason silently. VERIFIED 2026-08-02 S1-5
F-064 The verification step ordering in ExactStellarScheme._verify places auth-entry checks (expiry bound, credential type, sub-invocations, signature status) and transfer-event checks after simulateTransaction. Consequently, on a network where simulation cannot succeed, those codes are unreachable and every payload collapses to invalid_exact_stellar_payload_simulation_failed. Structural checks (version, scheme, network, operation shape, asset, function name, recipient, amount, facilitator safety) all precede simulation and remain reachable. Confirmed live in S2: expired and replayed payloads both surface as …_simulation_failed; wrong_amount fires pre-simulation. VERIFIED 2026-08-02 scheme.ts L385-551 @ SHA; S1-3, S1-4, S2-6

Session 2 — live conformance on stellar:testnet

ID Claim Status Date Source
F-065 v2 canonical wire headers are PAYMENT-REQUIRED (402), PAYMENT-SIGNATURE (paid request), PAYMENT-RESPONSE (receipt) — named canonical in specs/transports-v2/http.md §Header Reference and emitted by x402HTTPClient.encodePaymentSignatureHeader when x402Version === 2. X-PAYMENT/X-PAYMENT-RESPONSE are the v1 names (v1 emit branch; v1 fallback read). Observed live, casing as-sent, on the S2 transcript. Supersedes F-057. VERIFIED 2026-08-02 spec @ SHA; x402HTTPClient.ts L90-156; S2-2
F-066 An unmodified stock client completed a payment end-to-end through the walras facilitator on stellar:testnet: @x402/fetch buyer + @x402/express seller (both stock, zero custom protocol code), settled tx ac50c0910b3484ae6f2b070f35a95d1062dd3269cd4f877434dbcf2d7d3cc155 (ledger 3935588, successful, verified on Horizon and stellar.expert), 0.01 USDC buyer→seller, payer = buyer address. Full wire transcript captured by transparent taps. Q-011 closed. Note: the @x402/express middleware defaults maxTimeoutSeconds to 300, not the scheme spec's illustrative 60 (F-034 derivation unchanged). VERIFIED 2026-08-02 S2-2, S2-3
F-067 The repo e2e suite passes against walras: --facilitators=walras --families=stellar --testnet with servers {express, hono} × clients {fetch, axios} = 4/4 pass, each with a real on-chain settlement (hashes in S2-4, all verified on Horizon). walras ran as an external-proxy facilitator exec'ing the unmodified built dist. 11 e2e settlements total this session; every one charged exactly 22 973 stroops. VERIFIED 2026-08-02 S2-4; e2e/logs/walras-stellar-s2-final.*
F-068 Two e2e-harness defects at the pinned SHA, both invisible when the bundled all-family reference facilitator runs: (a) the mock facilitator omits batch-settlement from evmSchemes despite its stated claim-everything contract, killing every TS server's route validation under a non-EVM external facilitator; (b) servers/fastify never reads MOCK_FACILITATOR_URL, so it cannot start against any single-family facilitator at all. (a) fixed locally in scaffolding (one line); (b) excluded from the matrix. Both upstream-reportable. VERIFIED 2026-08-02 e2e/mock-facilitator/index.ts L28; grep MOCK_FACILITATOR_URL e2e/servers/*/index.ts; S2-4
F-069 Measured walras settlement fee: 22 973 stroops = 0.0022973 XLM, uniform across all 12 S2 settlements (max_fee 33 153). Exactly 100 stroops below the x402.org baseline's dominant cluster (23 073, F-054) — the delta is the baseline's fee-bump operation's own base fee (a fee bump pays for inner ops + 1). Q-008 cross-check closed: the RFP's "about 0.0023 XLM" holds for walras. Balance accounting exact: buyer −0.021 USDC, seller +0.021 USDC, facilitator −0.0275676 XLM = 12 × 22 973 stroops, and the facilitator held USDC at no point. VERIFIED 2026-08-02 S2-3; Horizon

Session 3 — discovery layer verification

ID Claim Status Date Source
F-070 node:sqlite (DatabaseSync) works on the pinned Node v24.14.0: file-backed DBs accept PRAGMA journal_mode=WAL (returns wal; :memory: DBs report memory, as SQLite defines), positional binding, transactions, and ON CONFLICT DO UPDATE all function. The module emits ExperimentalWarning — accepted as a pre-build risk in D-023. VERIFIED 2026-08-02 live probe; S3-1; test suite S3-2
F-071 @x402/extensions@2.20.0 is Apache-2.0; its transitive dependencies (@noble/curves, @scure/base, ajv, jose, @signinwithethereum/siwe, tweetnacl, viem, zod, @x402/core) are MIT / Apache-2.0 / Unlicense. Full-tree license scan re-run after install: PASS, zero copyleft. VERIFIED 2026-08-02 npm view; scripts/license-scan.mjs; S3-1
F-072 The SDK's one-shot extractDiscoveryInfo is not a trust boundary: it validates info only against the CLIENT-supplied schema (a trivial schema validates anything), never calls the exported validateDiscoveryExtensionSpec protocol-invariant check, discards rejection reasons into console.warn, and calls new URL(resource.url) unguarded (throws on a missing/malformed URL). A hardened facilitator must compose the low-level helpers itself. VERIFIED 2026-08-02 extensions/src/bazaar/facilitator.ts L475-579 @ SHA; demonstrated by the trivial-schema test, S3-2, and live S3-4
F-073 The stock @x402/core facilitator client parses EXTENSION-RESPONSES on verify/settle responses and console.logs fields from the allowlist ["status","rejectedReason","reason","code"] — so D-014's additive machine code is visible to unmodified consumers. Observed live: the stock seller middleware logged {"bazaar":{"status":"success"}} from walras's header. VERIFIED 2026-08-02 core/src/http/httpFacilitatorClient.ts L253-286 @ SHA; S3-3
F-074 @x402/express auto-registers bazaarResourceServerExtension when route configs declare bazaar extensions (checkIfBazaarNeeded → dynamic import → registerExtension), and x402HTTPResourceServer route config carries serviceName/tags/iconUrl through to the 402 resource block. A seller needs only declareDiscoveryExtension in route config — no explicit extension registration. VERIFIED 2026-08-02 http/express/src/index.ts L122-139 @ SHA; live 402 capture, S3-3
F-075 The full RFP 3.2 automatic-cataloging loop works live on stellar:testnet: stock buyer pays stock bazaar-declaring seller through walras (tx 81c4baac…9b3f, ledger 3936498, fee 22 973 stroops = F-069 exactly) → listing appears in GET /discovery/resources with zero registration steps → stock middleware logs the success header. Hostile payloads: a trivial-schema extension and a real settled wrong-payee payment (tx 66da7395…42d4) were both soft-dropped with machine codes (bazaar_spec_validation_failed, bazaar_listing_owned_by_other_payee) while their settlements succeeded on-chain. VERIFIED 2026-08-02 S3-3, S3-4; Horizon

Session 4 — search verification

ID Claim Status Date Source
F-076 node:sqlite on the pinned Node v24.14.0 bundles SQLite 3.51.2 compiled with SQLITE_ENABLE_FTS5: FTS5 virtual tables and bm25() work. bm25() returns negative scores, smaller = more relevant (ascending order = best first). Raw user text in MATCH throws (fts5: syntax error) on operator characters (", (, :, *, -, …), so untrusted queries must be compiled to quoted-token expressions before reaching the engine. VERIFIED 2026-08-03 live probe, PRAGMA compile_options; S4-2
F-077 Search pagination.limit is "Number of results in this page" — the returned count, per both the spec table and the SDK type comment — NOT the requested maximum, unlike the list endpoint's pagination.limit. pagination.cursor is "Cursor for the next page, or null if unavailable". VERIFIED 2026-08-03 specs/extensions/bazaar.md §GET /discovery/search @ SHA; facilitatorClient.ts L145-159

Docs session — documentation toolchain (gate GD.3)

ID Claim Status Date Source
F-084 Docs tooling licenses checked on the npm registry before install (gate GD.3): @mermaid-js/mermaid-cli@11.16.0 MIT, @redocly/cli@2.44.2 MIT, markdown-link-check@3.15.0 ISC, yaml@2.9.0 ISC. Zero copyleft at top level. The mermaid-cli transitive tree carries three dev-only findings (elkjs EPL-2.0, dompurify MPL-2.0-OR-Apache-2.0, khroma undeclared-but-MIT-on-disk) — none in any workspace project's production dependency closure (pnpm ls -r --prod). G-LIC re-run PASS under the two-tier policy of D-031. Extends the Q-012 toolchain pin (F-058). VERIFIED 2026-08-05 npm view (pre-install); pnpm why; on-disk license files; DECISIONS D-031; evidence §Docs
F-085 Stellar account reserves: one base reserve is 0.5 XLM, and every subentry — a trustline is one subentry — raises the account's minimum balance by one base reserve. Onboarding consequence: an account needs spare XLM above its current minimum before it can add the USDC trustline. Invisible on testnet (Friendbot funds 10 000 XLM); real on pubnet. VERIFIED 2026-08-05 developers.stellar.org — Fundamentals → Stellar data structures → Accounts (fetched 2026-08-05)
F-086 walras fee-bump settlement measured live: with FEE_BUMP_SECRET set, every settlement is a fee-bump envelope — Horizon shows fee_account ≠ source_account, fee_charged 23 073 stroops, max_fee 33 253, receipt carrying the outer (fee-bump) hash with the inner hash resolvable. Exactly +100 stroops over the single-submitter posture (F-069), confirming D-021's arithmetic, and byte-identical to the x402.org baseline's dominant fee anatomy (F-054, F-055). VERIFIED 2026-08-05 S7-1; Horizon tx 7519b950…9875

Session 6 — @x402/mcp and the MCP transport (gate G6.1)

ID Claim Status Date Source
F-078 @x402/mcp@2.20.0 is Apache-2.0. Runtime deps: @modelcontextprotocol/sdk ^1.12.1 (MIT), zod ^3.24.2 (MIT), @x402/core ~2.20.0 (Apache-2.0). Exports (from src/index.ts @ SHA): client x402MCPClient + factories createx402MCPClient / wrapMCPClientWithPayment(FromConfig); server createPaymentWrapper; constants MCP_PAYMENT_META_KEY = "x402/payment", MCP_PAYMENT_RESPONSE_META_KEY = "x402/payment-response", MCP_PAYMENT_REQUIRED_CODE = 402; meta attach/extract utils; createToolResourceUrlmcp://tool/{name}. VERIFIED 2026-08-05 npm view; typescript/packages/mcp/src/index.ts, types/mcp.ts @ SHA
F-079 MCP transport spec exists at the pinned SHA: specs/transports-v2/mcp.md. 402 signaling = tool result with isError: true carrying PaymentRequired in both structuredContent (REQUIRED) and content[0].text (REQUIRED, the JSON-stringified same object). Payment rides _meta["x402/payment"] (PaymentPayload); receipt rides _meta["x402/payment-response"] (SettlementResponse). Settlement failure after execution = same 402-shaped result, and the server should not return the tool's content — only the payment error. VERIFIED 2026-08-05 specs/transports-v2/mcp.md @ SHA
F-080 Division of labor: @x402/mcp provides the payment-aware MCP client (transparent 19-method passthrough; callTool detects 402-in-result and McpError -32042/SEP-1036, auto-pays, retries once on a corrective 402) and the server-side tool wrapper (createPaymentWrapper: verify → execute → settle via x402ResourceServer; on settle failure withholds tool content per spec). It provides no MCP server surface, no discovery/search tools, no MCP→HTTP bridge, and no catalog resolution — the walras packages/mcp-server (search_resources, paid_call) is entirely our build. Caveat: getToolPaymentRequirements probes by actually calling the tool — a free tool executes as a side effect. VERIFIED 2026-08-05 mcp/src/client/x402MCPClient.ts, mcp/src/server/paymentWrapper.ts @ SHA
F-081 Client-side spend-cap seam: x402Client.registerPolicy((x402Version, reqs) => reqs) filters PaymentRequirements[] before scheme selection and binds every transport sharing that client (HTTP wrapFetchWithPayment, MCP x402MCPClient). If policies filter everything out, payload creation throws "All payment requirements were filtered out by policies for x402 version: …". A 402 can also be inspected pre-payment: x402HTTPClient.getPaymentRequiredResponse(getHeader, body?) decodes the v2 PAYMENT-REQUIRED header (v1 body fallback), throwing "Invalid payment required response" otherwise. VERIFIED 2026-08-05 core/src/client/x402Client.ts L583-627; core/src/http/x402HTTPClient.ts L114-135 @ SHA
F-082 Where a listing's machine-readable calling convention lives differs by type. HTTP: extensions.bazaar.info.input = {type:"http", method, queryParams:<example values>} (query variant) or {type:"http", method, bodyType, body:<example values>} (body variant), while the JSON Schema for those params sits at extensions.bazaar.schema.properties.input.properties.queryParams (resp. .body). MCP: extensions.bazaar.info.input = {type:"mcp", toolName, inputSchema:<the actual JSON Schema>, description?, transport?, example?} — schema inline, not in the outer schema object. VERIFIED 2026-08-05 extensions/src/bazaar/http/resourceService.ts L24-153; mcp/resourceService.ts L19-45 @ SHA
F-083 x402ResourceServer.buildPaymentRequirements requires await resourceServer.initialize() first — it refuses kinds no facilitator has advertised, throwing "Facilitator does not support exact on stellar:testnet. Make sure to call initialize() …". The express middleware path hides this; a standalone createPaymentWrapper seller must call it explicitly, which also means the facilitator must be up before the seller boots. Hit live building demo/mcp-seller.ts. VERIFIED 2026-08-05 core/src/server/x402ResourceServer.ts L683-711 @ SHA; live boot failure + fix, S6-3

Adversarial audit — shipped-code security findings (gate hardening)

ID Claim Status Date Source
F-087 @x402/extensions validateDiscoveryExtension is ReDoS-exposed. It runs new Ajv({strict:false,allErrors:true}).compile(extension.schema) on the CLIENT's schema, compiling any pattern to a native RegExp with no safety policy, then validates the CLIENT's info. Measured against the installed @x402/extensions@2.20.0 dist: schema {pattern:"^(a+)+$"} + info "a"×n+"!" → n=28 2.3 s, n=30 9.2 s, n=32 36 s, ~4× per +2 chars; all payloads under 140 bytes = ~0.21 % of the 64 KiB indexer cap. Runs INLINE on the settle response path and Node is single-threaded, so it stalls concurrent requests after the transfer commits — falsifying "the byte cap bounds Ajv cost" (D-025). walras neutralizes it by stripping regex keywords + bounding node count before compile (D-033). VERIFIED 2026-08-14 dist read dist/cjs/bazaar/index.js L700-703; measured repro this session; D-033
F-088 The SDK's isValidRouteTemplate percent-decodes exactly once, so double-encoded traversal (%252e%252e), protocol-relative authorities (//host), and percent-encoded null bytes (%00) all return true. Measured against the installed dist. RFP task 3.B requires the facilitator to reject double-encoding, null bytes, and absolute/protocol-relative forms; delegating wholly to the SDK does not. walras adds hardenRouteTemplate (bounded repeated decode + null/backslash/protocol-relative rejection) ahead of the SDK check (D-033). VERIFIED 2026-08-14 dist read dist/cjs/bazaar/index.js L600-611; measured repro this session; D-033
F-089 The §7.1/§7.2 request envelope carries a top-level x402Version (integer) alongside paymentPayload and paymentRequirements; walras parses and echoes it (server.ts parseEnvelope, X402_VERSION = 2). The stock @x402/core facilitator client sends it and the reference facilitator requires it. VERIFIED 2026-08-14 specs/x402-specification-v2.md §7.1–7.2 @ SHA; packages/facilitator/src/server.ts; packages/facilitator/src/routeSchemas.ts

Session 0 follow-up — the second baseline and the docs deployment (2026-08-14)

ID Claim Status Date Source
F-090 A second live Stellar x402 facilitator exists and its stellar:testnet kind is byte-identical to x402.org's. periplo-testnet.fly.dev (periplo-facilitator, repo github.com/Eras256/Periplo) serves /supported 200 with exactly one kind — {"x402Version":2,"scheme":"exact","network":"stellar:testnet","extra":{"areFeesSponsored":true}} — field-for-field identical to the x402.org Stellar kind (F-041, S0-2). F-041 is therefore confirmed on two independent operators. Differences: one advertised Stellar signer (GDXULEKC…FLE) vs x402.org's two; no stellar:pubnet kind on either. VERIFIED 2026-08-14 evidence §S0-7 (live capture 2026-08-14T15:48:42Z)
F-091 periplo advertises extensions: ["bazaar"] and serves no discovery endpoint — the "advertised vs reachable" gap, live and in the direction that breaks clients. Both canonical bazaar endpoints 404 (/discovery/resources, F-025; /discovery/search, F-026), as do six near-miss spellings. Not a probe artifact: POST /verify on the same host returns 400 with {"isValid":false,"invalidReason":"invalid_request_shape",…}, so routing is live, and the facilitator's own service index lists only /health, /supported, /verify, /settle — it does not itself claim a discovery surface. Inverse of x402.org, which advertises no bazaar and serves none (F-042). Vindicates D-016 (advertise only what is reachable) with a live counterexample. VERIFIED 2026-08-14 evidence §S0-7; /supported + service index + 10 route probes, 2026-08-14
F-092 docs.walras.space is serving ce3d9ca while branch HEAD is c302fac — one commit stale. The deployed commit is read from the site's own footer stamp, the only deploy marker that exists (scripts/docs/build-site.mjs L33/L346 stamps git rev-parse --short HEAD at build time). ce3d9ca is a clean ancestor of c302fac (missed redeploy, not divergence); the undeployed delta is README.md + a 119-line rewrite of build-site.mjs, so the live site is rendered by the previous generation of its own builder. The site is deployed manually and out-of-band: the repository contains no deploy configuration and ci.yml has no pages or deploy job. VERIFIED 2026-08-14 evidence §Ops-1; curl https://docs.walras.space/; git merge-base --is-ancestor; scripts/check-site.sh

Policywright integration — a real production tool, paid by an agent with zero prior integration (2026-08-14)

ID Claim Status Date Source
F-093 The stock @x402/mcp createPaymentWrapper IS the server-side payment gate for an MCP tool — no walras-authored gate is needed (Q-019 answered). Proven end to end with a REAL production tool: Policywright (SCF #44), whose pure synthesize capability (recordedTx → least-privilege OpenZeppelin smart-account spec; no I/O, no clock reads, deterministic) is served as a paid MCP tool behind walras, priced $0.05 testnet USDC, payTo a fresh Policywright-owned testnet account GCC5HEDS…BLTOM (Friendbot-funded, USDC trustline), facilitator = walras. The tool declares its calling convention and discovery metadata via stock declareDiscoveryExtension({toolName:"synthesize", inputSchema, …}) — the F-082 mcp shape (info.input = {type:"mcp", toolName, inputSchema} + outer schema), attached through stock createPaymentWrapper after resourceServer.initialize() (F-083). A generic MCP agent with zero prior integration searched (empty → pay-to-list, D-004), paid the tool by (url, toolName) — that settlement cataloged it — then re-discovered it and paid it again by minted id. Two settled stellar:testnet txs: 3ff7309b…bf04 (ledger 4140963) and 980c3c59…8cc4 (ledger 4140965), fee 22 973 stroops each = F-069; identical recordedTx ⇒ byte-identical synthesized spec. Provenance: the integration lives in the Policywright repo (branch walras-x402-integration, integrations/walras-x402); walras imports nothing from Policywright, and Policywright's MCP-server tranche (T2) remains not-started — this is one early, deliberately minimal tool, not that deliverable. VERIFIED 2026-08-14 evidence §S6-4; Horizon txs; demo/policywright-session.ts; policywright@walras-x402-integration
F-094 The settle-gated ownership binding (D-024) holds on the MCP tuple, not only on HTTP URLs. Live poison-mcp attack: an attacker settles a real self-payment (structurally valid, on-chain) while echoing the Policywright tool's exact (resource.url, toolName) tuple with the attacker's own payTo and a well-formed mcp extension (passes schema validation, so the only possible rejection is the ownership check). Settlement succeeds on-chain; EXTENSION-RESPONSES reports bazaar.status:"rejected", code:bazaar_listing_owned_by_other_payee; the catalog entry is byte-identical and still owned by the Policywright payTo. The INVARIANT is preserved — indexing never throws and cannot change the settlement outcome. VERIFIED 2026-08-14 evidence §S6-4; demo/hostile-client.ts HOSTILE_MODE=poison-mcp; scripts/policywright-negative.sh

Multi-submitter round-robin — the last D-012 half, observed live (2026-08-15)

ID Claim Status Date Source
F-095 Round-robin across multiple submitter seeds observed live. With SUBMITTER_SECRET set to two comma-separated seeds and FEE_BUMP_SECRET unset, ./scripts/demo.sh settled five payments on stellar:testnet whose Horizon source_account strictly alternates between the two submitters — SUB1 GDM7S4RB…BIXC, SUB2 GADH5EHI…RP22 — ledgers 4152764/66/68/70/72, every fee_charged 22 973 stroops (= F-069), fee_account = source_account on all five (no fee bump, as configured). Settle latency measured at the facilitator: 3.44–7.21 s, median 5.18 s, 5/5 settled. One demo-side fix recorded in §S7-2: demo.sh's preflight rejected the comma-separated form config.ts documents and parses; the facilitator itself needed zero changes. VERIFIED 2026-08-15 evidence §S7-2; Horizon txs cccd8d5a…131a 515174c5…b854 3cf99b6b…69cc eba8ab92…dae7 f98f360f…5048

Q-009 traced — contract-account (__check_auth) payers (2026-08-15)

ID Claim Status Date Source
F-096 A contract account (C-address with custom __check_auth) can be the payer in exact-stellar, and the walras facilitator path supports it as-built (Q-009 traced). The pinned spec's auth-entry-signing pattern "Supports both C-accounts and G-accounts" and mandates sorobanCredentialsAddress credentials — the exact Soroban type that routes C-address auth through __check_auth; it imposes no signature-format rule (the strings __check_auth/"nonce"/"ed25519" never appear). The installed @x402/stellar@2.20.0 verify/settle path is address-type-agnostic by inspection: credential TYPE is checked, address type never; "signed" = signature ScVal ≠ scvVoid; zero package-side cryptography — validity is delegated to enforcing-mode simulation of the client-signed tx (which executes __check_auth) plus on-chain submission; settle copies auth entries verbatim into a facilitator-sourced envelope the legacy credential preimage does not bind. Binding constraints: V1 address credentials only (CAP-71 V2/delegates rejected), no extra subInvocations, no facilitator address in any auth entry, exact balance-change footprint, expiration cap, SEP-41 only. The blocker is client-side payload creation: the package's client scheme never plumbs the SDK's {signatureScVal} smart-wallet hatch, so its Ed25519 branch throws on C-addresses — external tooling must build the payload. Caveat stated plainly: traced from source and docs (36/36 claims adversarially re-verified), not an executed C-payer round-trip. VERIFIED (source trace) 2026-08-15 evidence §S0-8; spec @ 17fc9890 (sha256 34438214…7975); @x402/stellar@2.20.0 dist; @stellar/stellar-sdk@16.2.0 base/auth.js; developers.stellar.org authorization + simulation docs

Verification queue — status after Session 0

Gate G-FACTS: implementation does not start while any P0 row is OPEN.

ID Question Status Closed by
Q-001 bazaar.md shapes, filters, search, MCP keying, soft-drop, routeTemplate CLOSED F-023 … F-032
Q-002 scheme_exact_stellar payload format + validation requirements CLOSED F-033 … F-039
Q-003 /supported response incl. extra.areFeesSponsored CLOSED F-040 … F-043 (spec + live)
Q-004 e2e suite location, stellar:testnet invocation, env vars CLOSED F-056 (docs); F-067 (local run, 4/4 pass against walras).
Q-005 @x402/stellar facilitator surface; package vs wrapper validation split CLOSED F-044 … F-047
Q-006 facilitator-side cataloging helpers in @x402/extensions CLOSED — expectation was wrong F-048 … F-051
Q-007 Testnet USDC issuer + SAC contract ID, on-chain CLOSED F-052 (4 independent checks)
Q-008 Actual settlement fee on testnet CLOSED F-054 (live measurement, 0.0023073 XLM)
Q-009 Custom __check_auth account support (P1) CLOSED — traced (source analysis, not a live C-payer run) F-096: spec supports C-account payers by design; the installed facilitator path is address-type-agnostic and needs zero changes (signature validity rides on enforcing-mode simulation, which executes __check_auth); the blocker is client-side payload creation (the package never plumbs the SDK's {signatureScVal} hatch). Constraints enumerated in evidence §S0-8.
Q-010 Dependency license scan CLOSED — PASS F-060
Q-011 Live stock-client 402 → payment → settle transcript CLOSED F-066 (full transcript, settled tx, on-chain verification).
Q-012 Pin toolchain + @x402/* versions CLOSED F-058, F-059
Q-013 Wire header names/casing CLOSED F-057 (from SDK source, stronger than a transcript for casing)
Q-019 How a SERVER-side MCP tool declares payment requirements + discovery metadata per spec @ SHA, and whether @x402/mcp (or any official package) provides server-side gating CLOSED — an official gate exists; no walras helper needed F-080 (@x402/mcp createPaymentWrapper verifies → executes → settles server-side, withholding content on settle failure), F-082 (mcp discovery-metadata location), F-083 (initialize() ordering), and F-093 (the whole path proven live with a real external tool). The session-prompt fallback "if none exists, implement a walras gate" did not apply.

Q-011 — closed in Session 2

The blocker resolved exactly as predicted: the buyer account was funded with 20 testnet USDC via the captcha-gated Circle faucet (received 2026-08-02T09:23:00Z on-chain), and both Q-011 and the Q-004 local run closed in the same session. The round-trip evidence is S2-2/S2-3 (stock client, full transcript, settled tx ac50c091…cc155); the e2e run is S2-4. One Session 0 fact did not survive contact with the live wire: the header names in F-057 were the v1 branch — corrected by F-065 / D-018.


Update log

Date Change By
2026-07-31 Initial population from RFP fact-check (web-verified) + verification queue Kunal / Claude session
2026-08-02 Materialized into repo. Pinned spec SHA 17fc9890… written into header (G0.2). RFP captured verbatim to docs/rfp.md (G0.3). Claude session S0
2026-08-02 Session 0 verification: added F-023 … F-061 from pinned spec, package source, live capture, and on-chain measurement. Closed Q-001 … Q-008, Q-010, Q-012, Q-013. Q-011 blocked on captcha-gated USDC faucet; Q-009 partial (P1). Claude session S0
2026-08-02 Session 1 build: monorepo scaffold + packages/facilitator. Added F-062 … F-064 from package source and the published artifact. Added DECISIONS D-016 (do not advertise bazaar before it is reachable) and D-017 (test against a Soroban RPC double; label its results as modelled). Evidence S1-1 … S1-5. Q-011 unchanged — still OPEN and still the only blocker on a live round-trip. Claude session S1
2026-08-02 Session 2 conformance: buyer funded (Circle faucet) → Q-011 and Q-004 CLOSED. Stock @x402/fetch buyer paid a stock @x402/express seller through walras; tx ac50c091…cc155 verified on Horizon + stellar.expert. Repo e2e suite 4/4 against walras (express, hono × fetch, axios). Negative live tests (replay, amount mismatch, expired auth) each rejected with non-null reasons. Added F-065 … F-069; F-057 superseded (v1 headers). DECISIONS D-018 … D-021. Two upstream e2e-harness defects recorded (F-068). Evidence S2-1 … S2-6. Claude session S2
2026-08-02 Session 3 discovery: packages/bazaar (SQLite/WAL store on node:sqlite, hostile-input indexer, wire mapping) + facilitator settle hook, EXTENSION-RESPONSES, and GET /discovery/resources (seven filters, D-005). /supported now advertises bazaar (D-016 satisfied). 132/132 tests incl. poisoning suite. Live: automatic cataloging + two hostile soft-drops proven on stellar:testnet (F-075). Added F-070 … F-075; DECISIONS D-022 … D-025. Evidence S3-1 … S3-4. Claude session S3
2026-08-03 Session 4 search: gate G4.1 seeded the live catalog with 11 settle-gated listings (11 real settlements on stellar:testnet, S4-1). GET /discovery/search shipped spec-shaped (F-026 … F-028, F-077): query param, five filters, resources array, truthful partialResults, real keyset cursor pagination (D-003 honored; D-027). BASELINE retriever = FTS5/BM25 in node:sqlite (F-076, D-026) behind a Retriever seam. Eval harness pnpm eval:search: 28 labeled queries → recall@1 0.84, recall@3/5 0.93, MRR@10 0.91, nDCG@10 0.91 (S4-3). 157/157 tests. Live probes incl. hostile-syntax query and exactly-once cursor walk (S4-4). Added F-076, F-077; DECISIONS D-026, D-027. Claude session S4
2026-08-03 Session 5 demo + final assembly: gate G5.1 PASS (S2–S4 evidence present; clean-clone install/build/test exit 0; eval numbers reproduced in the clone). scripts/demo.sh one-command demo proven live: fresh empty catalog → first settlement auto-lists (EXTENSION-RESPONSES success) → agent searches /discovery/search, pays top hit via stock client (tx f2857a0b…3914, fee 22 973 = F-069) → catalog lastUpdated bumped. Negative flags --tampered/--expired/--poison-catalog each rejected live with machine reasons (S5-3), consistent with F-064/S2-6/S3-4. G-LIC re-run PASS. README quickstart timed from a real fresh clone: ≈100 s machine time incl. five settlements (S5-5); self-validation clone → README → demo exit 0. No new protocol facts — the session composed only verified components. Evidence S5-1 … S5-5. Claude session S5
2026-08-05 Docs session: gates GD.1–GD.4 PASS. Docs tooling license-checked pre-install (F-084); G-LIC rewritten two-tier (D-031) after mermaid's transitive tree surfaced three dev-only findings — shipped path stays zero-tolerance, PASS. R3 stop-condition fixed in code first: Fastify route schemas single-sourced (routeSchemas.ts, no-op compilers, wire behavior pinned by the suite), CONFIG_REFERENCE tables + drift-guard tests in both configs, SCHEMA_SQL exported; 213/213 tests. Generators shipped (pnpm docs:gen: OpenAPI 6 routes redocly-valid, config 8+4 vars, errors 64 codes/4 taxonomies, ERD 4 tables, 9 hash-marked SVGs) + pnpm docs:check gate (drift, OpenAPI, stale-SVG, links, claims audit) + CI workflow. Written: as-built ARCHITECTURE rewrite, MODELS, THREAT-MODEL, 7 diagrams, 3 role guides, quickstart, runbook, glossary, faq, SECURITY, CONTRIBUTING, litepaper (13 sections + LIMITATIONS) + ABSTRACT, 6 SCF snippets (docs/scf/*.md). docs:check PASS across 27 files; 10/10 spot-checked citations trace; post-refactor ./scripts/demo.sh re-run live: exit 0, agent tx b3fa66a2…7a054, fee 22 973 = F-069. Added F-084, F-085. Evidence §Docs. Git history rewritten on user request (Co-Authored-By trailers removed, all 16 commit dates byte-identical, force-pushed). Claude session Docs
2026-08-05 S7 fee-bump capture: the last "Not yet captured" row closed on user request — fee account created + funded, FEE_BUMP_SECRET set, ./scripts/demo.sh exit 0 with all five settlements through the fee-bump path; agent tx 7519b950…9875 Horizon-verified: fee_account ≠ source_account, fee 23 073 / max_fee 33 253 = the F-054 baseline anatomy byte-for-byte, delta over F-069 exactly the 100 stroops D-021 predicted. Added F-086; D-021 S7 follow-up; S7-1; stale "not yet captured" wording updated in ARCHITECTURE §5, runbook §4, operate.md §6, litepaper LIMITATIONS. Remaining unobserved: multi-submitter round-robin. Claude session Docs
2026-08-05 Session 6 MCP: gate G6.1 PASS (@x402/mcp@2.20.0 Apache-2.0, surface mapped from pinned source + installed artifact; MCP transport spec read at SHA; G-LIC re-run PASS with @modelcontextprotocol/sdk@1.30.0 MIT). packages/mcp-server shipped: search_resources + paid_call over stdio, dual-format deterministic results, facilitator error-enum passthrough (D-028), self-describing resource ids (D-029), double-enforced spend cap (D-030). 47 new tests (204 workspace total) — real MCP protocol over in-memory transports; chain seams doubled, labeled. Live S6-3: generic MCP client (zero walras imports) completed discover→pay using ONLY the two tools — paid an http listing by id (tx 79b541be…), paid a live MCP tool by (url, toolName) (tx d57ccaea…) whose settlement auto-cataloged it (F-029 tuple, closing the last "Not yet captured" row), re-discovered and re-paid it by minted id (tx 641f3e35…); all fees 22 973 stroops = F-069. Negative paths in-session: walras_mcp_unknown_resource_id, walras_invalid_search_cursor passthrough. Added F-078 … F-083; DECISIONS D-028 … D-030. Evidence S6-1 … S6-3. Claude session S6
2026-08-14 Policywright integration (S6 acceptance case): Q-019 CLOSED — the stock @x402/mcp createPaymentWrapper is the server-side payment gate (F-080), so no walras gate was written. Policywright's pure synthesize capability (SCF #44) served as a paid MCP tool behind walras from the Policywright repo (branch walras-x402-integration), priced $0.05 testnet USDC to a fresh Policywright-owned payTo. A zero-integration MCP agent searched (empty → pay-to-list), paid by (url, toolName) — cataloging the tool — then re-discovered and re-paid it by minted id: two settled txs 3ff7309b…/980c3c59…, fee 22 973 = F-069, deterministic synthesis (F-093). Live poison-mcp negative path: attacker echoing the tool's tuple with its own payTo settles on-chain but is bazaar_listing_owned_by_other_payee, catalog untouched (F-094 — D-024 holds on the MCP tuple). walras-side additions are generic and reusable: scripts/testnet-usdc.mjs (DEX USDC funding, no captcha), demo/hostile-client.ts poison-mcp mode, demo/policywright-session.ts + scripts/policywright-demo.sh/policywright-negative.sh, scripts/gate-s6.sh. Added F-093, F-094; DECISIONS D-037. Evidence §S6-4. Claude session (Policywright integration)
2026-08-14 Adversarial-audit hardening (parallel review session's findings, all reproduced against the installed dist before acting): (1) ReDoS — the SDK's validateDiscoveryExtension compiles the client schema's pattern to native RegExp; a ~140-byte evil-pattern payload measured 36 s of synchronous compute on the inline settle path (F-087). Fixed: boundSchemaForValidation strips regex keywords + caps node count before Ajv; new bazaar_schema_too_complex code (D-033). (2) routeTemplate under-decode — the SDK decodes once, so %252e%252e / //host / %00 pass (F-088); added hardenRouteTemplate (bounded repeated decode + null/backslash/protocol-relative rejection) per RFP 3.B (D-033). (3) soft_drops audit table (RFP 3.A) + per-field drop logging. (4) same-owner update now merges, closing a same-owner metadata-blanking vector (D-033). (5) URL squatting made honest: attacker-FIRST regression test pins real behavior, THREAT-MODEL row 52 reframed, S3-4 scoped, D-032 records it as a disclosed limitation (grant-scope fix = proof-of-origin-control). Bazaar suite 64→76. Added F-087 … F-089; DECISIONS D-032, D-033. Hygiene: fee overclaims re-scoped to F-069 (single-submitter) vs F-086 (fee-bump) across README + 8 docs; real clone URL; .env.example DB_PATH; demo/ typechecked; gate scripts materialized. INVARIANT preserved: the indexer still never throws and cannot change a settlement outcome. Claude session (audit follow-up)
2026-08-14 Ledger-gap closure — two untracked gaps and one false claim, all recorded rather than quietly fixed. (1) Second baseline (S0 DoD), 12 days late: periplo-testnet.fly.dev captured live — stellar:testnet kind byte-identical to x402.org's, confirming F-041 on two independent operators (F-090); it advertises extensions:["bazaar"] yet 404s both canonical discovery endpoints and its own service index claims no discovery surface (F-091) — the RFP's "advertised vs reachable" caution observed in the wild, vindicating D-016. D-010 amended: no discovery baseline still, but now because the one operator claiming Bazaar does not implement it. The process failure — the gap was never tracked as outstanding — recorded as D-034, not backdated. (2) docs.walras.space: measured for the first time — deployed ce3d9ca vs HEAD c302fac, one commit stale, rendered by the previous generation of its own builder (F-092); scripts/check-site.sh + pnpm check:site now read the footer stamp back off the live site, deliberately outside CI (D-035). (3) Upstream findings: D-002, D-009, D-019, D-020 were marked UPSTREAM since 2026-08-02 but never filed — zero issues opened. Statuses changed to FOUND, NOT FILED (D-036); the litepaper's "queued upstream" and maintenance.md's "upstream divergences are reported" corrected, the latter having read as a track record for an empty backlog. Added F-090 … F-092; DECISIONS D-034 … D-036; S0-7, Ops-1; four "Not yet captured" rows added incl. multi-submitter round-robin. Claude session (ledger gaps)
2026-08-15 Round-robin capture: the last technical "Not yet captured" row closed — a second Friendbot-funded submitter added to SUBMITTER_SECRET (comma-separated), ./scripts/demo.sh exit 0 with five settlements whose Horizon source_account strictly alternates SUB1/SUB2/SUB1/SUB2/SUB1, all fees 22 973 = F-069, median settle 5.18 s, 5/5 settled. One demo-side fix: demo.sh preflight now validates each seed of the comma-separated form (it rejected the format config.ts documents; facilitator untouched). Added F-095; D-021 S7-2 follow-up; S7-2. Q-009 CLOSED by source trace (F-096, S0-8): C-account payers are spec-supported and the installed facilitator path needs zero changes — enforcing-mode simulation executes __check_auth; the blocker is client-side payload creation; 36/36 claims adversarially re-verified against cited lines; explicitly NOT a live C-payer run. Also added .github/workflows/live-settle.yml — a stock-client settlement on every push with Friendbot-created run-time accounts and DEX-bought USDC, so the repo holds no secrets and any fork reproduces the settlement — and clean URLs for docs.walras.space (build-site.mjs emits extensionless links + vercel.json cleanUrls; old .html deep links 308-redirect; takes effect on the next manual deploy, D-035). Claude session (leftovers)